GOF的《设计模式-可复用面向对象软件的基础》一书中对设计模式做了两个标准的划分:
第一条是目的准则:模式用来完成什么工作,根据目的可划分为:创建型、结构型、行为型;创建型涉及对象的创建,结构型处理类或对象的组合,行为型对类或对象如何交互和怎样分配职责进行描述。
第二条是范围准则:指定模式主要用于类还是对象。类模式是处理类和子类之间的关系,这些关系通过继承实现,编译时期已经确定;对象模式是处理对象之间的关系,这些关系在运行时刻是可变的,更具有动态性。大多数模式还是这一类范畴。
在该书中并没有简单工厂的概念,但《Java与模式》与《Thinking in Patterns》两书均对该模式进行了详细的介绍,这里进行一下学习总结。
简单工厂模式又称“静态工厂方法模式”,也就是创建产品对象是由一个静态方法实现的,这个静态方法负责生产具有共同接口的类的对象,就像工厂生产产品一样,所以叫静态工厂方法,这里给出代码,然后对其进行分析:
1 package simplefac; 2 public class SimpleFactory{ 3 4 public static Fruit factory(String str) throws RuntimeException{ 5 if("Apple".equals(str)){ 6 System.out.println("produce apple"); 7 return new Apple(); 8 } 9 else if("Grape".equals(str)){ 10 System.out.println("produce grape"); 11 return new Grape(); 12 }else{ 13 throw new RuntimeException("we don't produce such fruit!"); 14 } 15 } 16 } 17 class Fruit{ 18 19 public void taste(){}; 20 public void color(){}; 21 } 22 class Apple extends Fruit{ 23 24 public void taste(){ 25 System.out.println("I'm Sweet"); 26 } 27 public void color(){ 28 System.out.println("I'm Red"); 29 } 30 } 31 class Grape extends Fruit{ 32 33 public void taste(){ 34 System.out.println("I'm Sour"); 35 } 36 public void color(){ 37 System.out.println("I'm Purple"); 38 } 39 }
我们定义了一个Fruit类,作为各种水果的顶层抽象描述,只有taste和color两个方法,作为对水果口味和颜色的描述;又创建了两个子类,分别是苹果和葡萄, 这里,为了方便起见,将它们暂且放在具有静态工厂方法的SimpleFactory同一个Java文件中,下面给出测试方法:
1 package simplefac; 2 public class Test{ 3 public static void main(String[] args){ 4 try{ 5 SimpleFactory.factory("Apple").color(); 6 SimpleFactory.factory("Grape").color(); 7 SimpleFactory.factory("Orange").color(); 8 }catch(Exception e){ 9 e.printStackTrace(); 10 } 11 } 12 }
从测试结果可以看出,静态工厂方法会根据你的传值生产相应的水果,它就像一个万能的窗口,客户只要对它喊“我要苹果”,它就返给你苹果,如果它没有你想要的水果,它就抛出一个异常,并提醒“我没有这样的水果”,这时候如果想让它生产这种水果的话,就必须对它修改,这里总结一下简单工厂模式的优缺点:
优点:实现了责任分割,客户端(想要水果的一方)免去了自行生产水果的责任,统一由静态工厂方法来处理。
缺点:具有静态工厂方法的工厂类拥有创建所有产品的逻辑判断,一旦该类不能正常工作,所有的产品就都不能正常生产了。而且它对设计模式的“开-闭原则”的支持力度不够。
“开-闭原则”原则是指要求一个系统设计能够在原系统不做修改的情况下,扩展系统功能。这里如果创建“Orange”对象,必须添加定义Orange类,这叫功能扩展,但是是不是不需要修改系统了呢?通过分析可知:有一处我们一定要修改,那就是生产水果的静态工厂方法,你需要再添加一个判断语句并给出Orange类对象的创建语句,所以还是对系统做了一定的修改,有没有方法避免修改呢?当然有,下次再做总结。