《JAVA与模式》之简单工厂与工厂方法
一、简单工厂
1.1 使用场景
1、工厂类负责创建的对象比较少;
2、客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
3、由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。
1.2 优缺点
优点:
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点:
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
这些缺点在工厂方法模式中得到了一定的克服。
1.3 结构与角色
a、简单工厂模式类图:
该模式中包含的角色及其职责:
1、工厂(Creator)角色
简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
2、抽象产品(Product)角色
简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
3、具体产品(Concrete Product)角色
是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。
具体代码:
1 //抽象产品角色 2 interface Board{ 3 4 public void createBoard(); 5 } 6 //具体产品角色 7 class GigabyteBoard implements Board{ 8 9 public void createBoard() { 10 // TODO Auto-generated method stub 11 System.out.println("生产-->技嘉主板"); 12 } 13 } 14 //具体产品角色 15 class AsusBoard implements Board{ 16 17 public void createBoard() { 18 // TODO Auto-generated method stub 19 System.out.println("生产-->华硕主板"); 20 } 21 } 22 //工厂角色 23 class SimpleFactory { 24 public static Board factory(String type){ 25 26 if(type.equalsIgnoreCase("gigabyte")){ 27 28 return new GigabyteBoard(); 29 }else if(type.equalsIgnoreCase("asus")){ 30 31 return new AsusBoard(); 32 } 33 return null; 34 } 35 }
调用代码:
1 //简单工厂 一个静态方法 自身负责创建产品 2 Board board=SimpleFactory.factory("asus"); 3 board.createBoard();
二、工厂方法
2.1 定义
工厂方法模式的用意是定义一个创建产品的工厂接口,将实际创建工作推迟到子类中。
其实工厂方法模式是简单工厂的一种延伸,在简单工厂模式中,一个工厂类处于对产品类实例化的中心位置上,他操纵所有下面的产
品类的实例化,当每次新加一个产品类的时候都要在工厂类里面进行修改。工厂方法模式就是解决这个缺点而来的,工厂方法模式把
创建每个产品实例化的工作交给了子类去做。成为一个抽象工厂,仅负责给具体工厂子类必须实现的接口,而不接触具体实例化的细
节。这样的核心工厂类就成为了一个抽象工厂角色,这样进一步的抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角
色的情况下引进新的产品。
2.2 结构与角色
抽象工厂角色(Creator)
工厂方法模式的核心,任何工厂类都必须实现这个接口。
。具体工厂角色(Concrete Creato)
具体工厂类是抽象工厂的一个实现,负责实例化产品对象。
。抽象角色(product)
工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
。具体产品角色
工厂方法模式所创建的具体实例对象。
具体代码:
1 //抽象工厂 2 interface ComputerFactory{ 3 public Computer createComputer(); 4 } 5 //具体工厂 6 class SamsungComputerFactory implements ComputerFactory{ 7 8 public Computer createComputer() { 9 return new SamsungComputer(); 10 } 11 } 12 class HpComputerFactory implements ComputerFactory{ 13 14 public Computer createComputer() { 15 return new HpComputer(); 16 } 17 } 18 19 //抽象产品 20 interface Computer{ 21 22 23 public double price(); 24 25 public double weight(); 26 } 27 //具体产品 28 class SamsungComputer implements Computer{ 29 30 public double price() { 31 // TODO Auto-generated method stub 32 return 8000; 33 } 34 public double weight() { 35 // TODO Auto-generated method stub 36 return 5.2; 37 } 38 } 39 class HpComputer implements Computer{ 40 41 public double price() { 42 // TODO Auto-generated method stub 43 return 5000; 44 } 45 public double weight() { 46 // TODO Auto-generated method stub 47 return 4.2; 48 } 49 }
调用代码:
1 ComputerFactory factory=new SamsungComputerFactory(); 2 Computer computer=factory.createComputer(); 3 System.out.println(computer.price());
什么时候使用工程方法
1) 当客户程序不需要知道要使用对象的创建过程。
2) 客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。
小结:
简单工厂模式与工厂方法模式真正的避免了代码的改动了?没有。在简单工厂模式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么将判断逻辑留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就象上面的例子一样)。而且产品
对象创建条件的改变必然会引起工厂角色的修改。
面对这种情况,Java 的反射机制与配置文件的巧妙结合突破了限制——这在Spring 中完美的体现了出来。
参考:
http://blog.csdn.net/yuan22003/article/details/6709649
http://www.cnblogs.com/java-my-life/archive/2012/03/25/2416227.html
http://men4661273.iteye.com/blog/1638379