写点什么

【架构师训练营 - week3 -2】总结

用户头像
早睡早起
关注
发布于: 2020 年 06 月 25 日
【架构师训练营 - week3 -2】总结

策略模式

策略模式可以定义为,定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。

基于一个简单的例子来看一下,假设我们明天中午吃饭有三种选择,泡面,订外卖,煮饺子。要做选择可以这么做

首先定义一个接口

interface Lunch{
public void eat();
}


具体的实现类如下

public class InstantNoodle implements Lunch{
public void eat(){
//eat InstantNoodle;
}
}

public class TakeAway implements Lunch{
public void eat(){
//eat takeaway;
}
}

public class Dumplings implements Lunch{
public void eat(){
//eat dumplings;
}
}



其实这时候而言,我们的功能已经算完成了。为了保证选择的封装性,便捷切换以及良好的扩展性,我们可以为他增加一个封装类,在策略模式中通常叫做Context。

public class Context{
private Lunch lunch = null;
public Context(Lunch lunch){
this.lunch = lunch;
}
private void toEat(){
lunch.eat();
}
}


这时候如果第二天我选择我要吃的东西就可以使用如下方式:

public class Main{
public static void main(String[] args) {
//想吃泡面
Context context = Context(new InstantNoodle());
context.eat();
}
}


对于策略模式而言,我们可以使用如下的类图来进行表示:



优势与缺点

优点
  • 算法可以自由的切换

  • 避免多重条件的判断

  • 扩展性好

缺点
  • 策略种类多

  • 策略类需要对外暴漏

应用场景

在JDK中的ThreadPoolExecutor使用了策略模式,它预定了4中策略:

ThreadPoolExecutor.AbortPolicy()
ThreadPoolExecutor.CallerRunsPolicy()
ThreadPoolExecutor.DiscardOldestPolicy()
ThreadPoolExecutor.DiscardPolicy()


可以看到每个策略都被放在一个单独的类中

public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }

/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}


工厂模式

这里不再举例实际的工厂例子,实际的例子可以参照我的这篇文章

特征和优缺点

我们知道工厂模式可以分为简单工厂模式,工厂方法模式和抽象工厂模式,我们简单来讨论下他们的特点和优缺点。

简单工厂模式

优点是比较简单,简化了类的创建过程。

缺点是工厂类的扩展比较困难,不符合开闭原则。

工厂方法模式





使用案例

1.如果使用JDBC连接数据库,数据库从MySQL切换到Oracle,需要改动的地方就是切换一下驱动名称(前提条件是SQL语句是标准语句),其他的都不需要修改,这是工厂方法模式灵活性的一个直接案例。



2.在实际的单元测试应用中,如果要测试一下代码

Class TestA{
public int test(){
DoSomeThing dst = new DoSomeThing();
dst.run();
}
}


因为方法体创建的对象使用一般的Mockito是不能进行mock的,这时候我们可以构造一个工厂方法。

Class Factory{
public DoSomeThing build(){
return new DoSomeThing ();
}
}


新的代码可以写为

Class TestB{
Factory factory = new Factory();
public int test(){
DoSomeThing s = factory.build();
s.run();
}
}


这样便可以进行mock,顺利完成单元测试。

抽象工厂方法



抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。

抽象工厂方法的优势

  • 封装性

  • 产品族内的约束为非公开状态

应用场景

例如一个应用,需要在三个不同平台(Windows、Linux、Android),通过抽象工厂模式屏蔽掉操作系统对应用的影响。三个不同操作系统上的软件功能、应用逻辑、UI都应该是非常类似的,唯一不同的是调用不同的工厂方法,由不同的产品类去处理与操作系统交互的信息。



用户头像

早睡早起

关注

还未添加个人签名 2019.09.05 加入

还未添加个人简介

评论

发布
暂无评论
【架构师训练营 - week3 -2】总结