Eason-S

导航

每天一个设计模式(5):工厂方法模式

5.工厂方法模式

  工厂方法模式是简单工厂模式的进一步抽象化和推广,工厂方法模式里不再只由一个工厂类决定那一个产品类应当被实例化,这个决定被交给抽象工厂的子类去做。工厂方法模式定义了一个创建对象的接口,让类把实例化推迟至子类。

  工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“女娲类”。这样分担了对象承受的压力;而且这样使得结构变得灵活起来——当有新的产品产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。工厂角色的结构也是符合开闭原则的。

一.要点

  • 所有的工厂都是用来封装对象的创建。
  • 工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象。
  • 工厂方法将客户(也就是超类中的代码,如orderPizza())和实际创建具体产品的代码分隔开来。
  • 工厂方法可能需要参数(也可能不需要)来指定所需要的产品。

依赖倒置原则:要依赖抽象,不要依赖具体类。

几个指导方针帮助你遵循此原则:

  • 变量不可以持有具体类的引用。如果使用new,就会持有具体类的引用,可以使用工厂来避开这样的做法。
  • 不要让类派生自具体类。如果派生自具体类,就会依赖具体类。要派生自抽象类或接口。
  • 不要覆盖基类中已实现的方法。如果覆盖基类已实现的方法,那么基类不是一个真正适合被继承的抽象。基类中已实现的方法应该由所有的子类共享。

  这些原则应尽量达到,而不是随时都要遵循,有时候有足够的理由,就可以违反这些方针。

二.UML关系图

由上图我们可以看到工厂方法模式由四部分组成:

  • 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
  • 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
  • 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
  • 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

三.实现代码

 1 //抽象产品角色
 2 public interface Moveable {
 3     void run();
 4 }
 5 //具体产品角色
 6 public class Plane implements Moveable {
 7     @Override
 8     public void run() {
 9         System.out.println("plane....");
10     }
11 }
12 
13 public class Broom implements Moveable {
14     @Override
15     public void run() {
16         System.out.println("broom.....");
17     }
18 }
19 
20 //抽象工厂
21 public abstract class VehicleFactory {
22     abstract Moveable create();
23 }
24 
25 //具体工厂
26 public class PlaneFactory extends VehicleFactory{
27     public Moveable create() {
28         return new Plane();
29     }
30 }
31 public class BroomFactory extends VehicleFactory{
32     public Moveable create() {
33         return new Broom();
34     }
35 }
36 
37 //测试类
38 public class Test {
39     public static void main(String[] args) {
40         VehicleFactory factory = new BroomFactory();
41         Moveable m = factory.create();
42         m.run();
43     }
44 }

四.应用场景

在以下情况下,适用于工厂方法模式:

(1) 当一个类不知道它所必须创建的对象的类的时候。

(2) 当一个类希望由它的子类来指定它所创建的对象的时候。

(3) 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

  由示例代码可以看出工厂方法,使得对象的数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。因为如果不能避免这种情况,可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。

五.简单工厂和工厂方法模式的比较

  工厂方法模式和简单工厂模式在定义上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而不像简单工厂模式,把核心放在一个实类上。工厂方法模式可以允许很多实的工厂类从抽象工厂类继承下来,从而可以在实际上成为多个简单工厂模式的综合,从而推广了简单工厂模式。
  反过来讲,简单工厂模式是由工厂方法模式退化而来。设想如果我们非常确定一个系统只需要一个实的工厂类,那么就不妨把抽象工厂类合并到实的工厂类中去。而这样一来,我们就退化到简单工厂模式了。

 

参考:《Head First设计模式》

http://www.cnblogs.com/forlina/archive/2011/06/21/2086114.html

http://www.cnblogs.com/mengdd/archive/2013/01/04/2844868.html

http://www.cnblogs.com/devinzhang/archive/2011/12/19/2293160.html

posted on 2016-07-18 17:54  Eason_S  阅读(343)  评论(0编辑  收藏  举报