1. 简单工厂模式
在阎宏博士的《JAVA与模式》一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
先放图再解释。下图一是从《大话设计模式》中摘出来的。问题是:用任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果。
简单工厂模式实现的关键点有两个:
1. 继承:定义一个抽象父类“抽象产品”(Operation类),和一堆具体的子类“实际产品”(OperationAdd等子类)。抽象父类的设计是非常重要的(属性、方法)
2. 关联关系:定义一个“工厂类”,他提供生产产品的方法(图中createOperate()),然后返回一个产品(Operation类)。关联关系使一个类知道另一个类的属性和方法。
解决问题:如何实例化一个合适的对象
扩展方法:新增“产品”子类,并修改“工厂类”的创建逻辑。
使用方法:使用工厂类创建产品类,然后调用产品方法或属性。(客户端了解两个类:工厂类和产品抽象类)
优点:简单。但应用很广哦
缺点:每次还需要修改创建逻辑,如果创建逻辑挂掉,整个就挂了。 而且每次扩展都要修改“工厂类”代码,这就需要重新编译部署代码。
使用场景:负责创建的对象比较少;客户只知道传入工厂的参数,不关心对象创建逻辑。 容易违反高内聚低耦合,一般只在很简单的情况下使用。
图一. 简单工程模式类图示例
1 class Test{ 2 public static void main( String[] args ){ 3 Operation oper; 4 OperationFactory operFac = new OperationFactory(); 5 oper = operFac.createOperation("+"); 6 oper.setOpA(1); 7 oper.setOpB(2); 8 oper.getResult(); 9 } 10 } 11 12 class OperationFactory{ 13 public Operation createOperation( String op ){ 14 if( op == "+" ) return new OperationAdd(); 15 if( op == "-" ) return new OperationMinus(); 16 if( op == "*" ) return new OperationMultiply(); 17 return new OperationDivide(); 18 } 19 } 20 21 abstract class Operation{ 22 private double opA; 23 private double opB; 24 25 public double getOpA() { 26 return opA; 27 } 28 29 public void setOpA(double opA) { 30 this.opA = opA; 31 } 32 33 public double getOpB() { 34 return opB; 35 } 36 37 public void setOpB(double opB) { 38 this.opB = opB; 39 } 40 41 public abstract double getResult(); 42 } 43 44 class OperationAdd extends Operation{ 45 public double getResult(){ 46 return getOpA() + getOpB(); 47 } 48 } 49 50 class OperationMinus extends Operation{ 51 public double getResult(){ 52 return getOpA() - getOpB(); 53 } 54 } 55 56 class OperationMultiply extends Operation{ 57 public double getResult(){ 58 return getOpA() * getOpB(); 59 } 60 } 61 62 class OperationDivide extends Operation{ 63 public double getResult(){ 64 if( getOpB() == 0 ) 65 try { 66 throw new Exception("除数不能为0"); 67 } catch (Exception e) { 68 } 69 return getOpA() / getOpB(); 70 } 71 }
2. 策略模式
在阎宏博士的《JAVA与模式》一书中开头是这样描述策略(Strategy)模式的:
策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
先放图再解释。下图二是从《大话设计模式》中摘出来的。问题实例是:做一个商场收银软件,根据客户购买商品的单价和数量,向客户收费。而商场可能做活动:打折、满减、满返之类的。
策略模式实现的关键点有两个:
1. 继承:实现某个功能需要一个“抽象算法类”(Strategy),算法可以有不同的实现,这些”具体算法类“(ConcreteStrategy)继承”抽象算法类“的通用接口。(Strategy类的接口设计是很重要的)
2. 聚合关系:对算法的使用进行封装,即提供一个算法的对外接口(Context类),Context类持有一个Strategy,把算法的使用和算法本身分开。 Context里有算法,但这个算法具体是啥,根据上下文不同,可能会是不同的算法。在什么样的情况下,配置采用哪个算法来实现,这就是Context的工作。用户只需要提供上下文给Context,然后Context就提供调用算法的接口。这个时候,Context和Strategy的关系更密切,它充当了算法与客户之间的接口,客户完全接触不到Strategy类了,但是Context完全了解Strategy。 (聚合关系中,整体和个体是“has-a”的关系,整体部分可分离。)
扩展方法:新定义一个符合Strategy接口定义的算法,在Context里重新添加这一配置(如果采用反射,则可以避免这部分代码的修改,只需新定义ConcreteStrategy就好了,这个以后会讲)
使用方法:用户向Context传递上下文,然后调用Context的算法接口方法就好了。(客户端了解一个类:Context类)----这个可能是要和简单工厂模式联合使用
优点:
(1)提供管理相关算法的协议。同类算法实现不同,但有相同的行为特征,还可以把公共代码放到父类,避免冗余。
(2)封装算法变化。
1 class Context{ 2 Strategy str; 3 public Context( Strategy str ){ 4 this.str = str; 5 } 6 7 public void contextInterface(){ 8 str.algorithmInterface(); 9 } 10 } 11 12 public abstract class Strategy { 13 public abstract void algorithmInterface(); 14 } 15 16 class ConcreteStrategyA extends Strategy{ 17 public void algorithmInterface(){} 18 } 19 20 class ConcreteStrategyB extends Strategy{ 21 public void algorithmInterface(){} 22 } 23 24 class ConcreteStrategyC extends Strategy{ 25 public void algorithmInterface(){} 26 }
图二.策略模式类图
3. 总结
策略模式和简单工厂模式的几点不同:
- 策略模式有两层封装。第一,把具体算法封装到Strategy:所有实现相同功能的算法继承这个类;第二, 把算法封装起来,只提供用户需要的功能:用Context把算法封装起来,Context定义用户可以使用的接口,Context确定使用哪个算法实现用户要求的具体功能。
- 简单工厂模式有一层封装。把产品封装到Product类,并提供生产产品的方法。即没有策略模式中的第二层封装,这里用户需要完成配置产品的动作,虽然使用工厂方法,这个配置动作简单了一些,但是用户还是要执行。但是策略模式中,用户根本就不需要去了解任何配置的事情,也不需要了解算法的存在。
- 策略模式的应用强调:相同行为不同实现的算法封装。算法和产品的不同在于,算法原本只是为了实现对象的某个行为,由于实现经常变动,因此把这种经常改变的部分提取出来,作为一个抽象类封装起来。 所以说策略模式属于对象行为模式。
- 简单工厂模式的应用强调:相同类别产品的封装。产品关注的是一个个的对象。所以简单工厂模式属于类的创建型模式。
- 这两种模式都不注重实现,都是在于如何组织、调用产品或算法,所以抽象出一些新的类实现这些管理功能。----设计模式有点参考管理学的东西吧。