设计模式-工厂方法模式

时间:2022-10-02 14:24:06

android中用到了太多的工厂类,其中有用工厂方法模式的,当然也有很多工厂并不是使用工厂方法模式的,只是工具管理类。
今天以ThreadFactory举例说明一下简单工厂模式和工厂方法模式。 
工厂方法模式,Factory Method,简单的方式,不简单的应用。

1.意图
定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方式模式使一个类的实例化延迟到其子类。
热门词汇:虚构造器 延迟 创建对象 子类 

2.结构图和代码
我们先看看标准的工厂方法结构图:

设计模式-工厂方法模式
先抽象的产品类,抽象的工厂类,然后用客户端具体的工厂生产相应的具体的产品,但是客户端并不知道具体的产品是怎么生产的,生产的过程封装在工厂里。所以说,某种程度上,工厂方法模式改变了我们直接用new创建对象的方式,一个很好的开始,意义重大。
以ThreadFactory为例:

设计模式-工厂方法模式

这张图其实和原本的结构图有细微的区别,那就是参数化得工厂,而且从业务意义上也有些不同,但是思想是一样的。
我们来看下具体的代码:

  1. //抽象产品  
  2. public interface Runnable {  
  3.     public abstract void run();  
  4. }  
  5.    
  6. //抽象工厂  
  7. public interface ThreadFactory {  
  8.     Thread newThread(Runnable r);  
  9. }  

下面是具体的实现:
比如AsyncTask类中工厂的具体实现如下:

  1. //工厂实现类  
  2. private static final ThreadFactory sThreadFactory = new ThreadFactory() {  
  3.     private final AtomicInteger mCount = new AtomicInteger(1);  
  4.   
  5.     public Thread newThread(Runnable r) {  
  6.         return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());  
  7.     }  
  8. };  
  9. //那么产品类在哪里呢?  
  10. //做为参数Runnable r,我们可以创建千千万万个此系列的产品类  
  11. //同理,我们可以创建另外类似的工厂,生产某种专门的线程,非常容易扩展  

看到这里,我们一方面为它的生产便利性感叹,一方面又为没创建某类产品都要创建一个工厂而感到繁琐,所以我们下面介绍简单工厂,它的结构图如下:

设计模式-工厂方法模式
简单工厂把抽象工厂去掉了,你就创建一个专门生产某类产品就好。在一些特定而又不负责的领域非常实用方便套用这个模式。
在android中的Connection类中使用到了这个类:

设计模式-工厂方法模式
其中Connection这个抽象类,既充当抽象产品类,也充当具体工厂类。
因为这种情况下,我们往往需要的是马上生产子类,getConnection方法往往是静态的,所以简单工厂,也叫静态工厂方法。
我们看看代码如下:

  1. abstract class Connection{      
  2.     static Connection getConnection(  
  3.             Context context, HttpHost host, HttpHost proxy,  
  4.             RequestFeeder requestFeeder) {  
  5.    
  6.         if (host.getSchemeName().equals("http")) {  
  7.             return new HttpConnection(context, host, requestFeeder);  
  8.         }  
  9.    
  10.         // Otherwise, default to https  
  11.         return new HttpsConnection(context, host, proxy, requestFeeder);  
  12.     }  
  13. }  

这就是简单工厂,一个很简单的参数化工厂,真的很简单。

3.效果
1.创建型模式;
2.参数化工厂方法模式得到相应的对象;
3.为子类提供挂钩;
4.连接平行的类层次。

另外一个例子:

 

先假设要做这样的一个设计。设计一个Usb功能的接口,具有store(存储)和takeAlong(携带方便)两个行为。然后要设计两个产品,一个是 Phone(手机),另一个是Camera(照相机),很显然,它们都可以是 Usb的实现类。为了便于统一管理和创建,我们很容易就能设计出一个简单的工厂模式。

(1)普通的工厂方法

首先,我们可以画出相关的设计图:

设计模式-工厂方法模式

代码实现如下:

定义Usb接口

 

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. public interface Usb {  
  2.   
  3.     void store();  
  4.   
  5.     void takeAlong();  
  6. }  

Phone类

 

 

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. public class Phone implements Usb {  
  2.   
  3.     @Override  
  4.     public void store() {  
  5.   
  6.         System.out.println("this is Phone usb!");  
  7.     }  
  8.   
  9.     @Override  
  10.     public void takeAlong() {  
  11.         // TODO Auto-generated method stub  
  12.   
  13.     }  
  14.   
  15.     public void call() {  
  16.         //TODO  
  17.     }  
  18.   
  19.     public void sms() {  
  20.         //TODO  
  21.     }  
  22.   
  23. }  

Camera类

 

 

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. public class Camera implements Usb {  
  2.   
  3.     @Override  
  4.     public void store() {  
  5.         System.out.println("this is Camera usb!");  
  6.     }  
  7.   
  8.     @Override  
  9.     public void takeAlong() {  
  10.         // TODO Auto-generated method stub  
  11.   
  12.     }  
  13.   
  14.     public void takePhotos() {  
  15.         //TODO  
  16.     }  
  17.   
  18. }  

创建一个简单的工厂类UsbFactory1,负责生产

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. /** 
  2.  * 普通工厂方法 
  3.  * 参数传递的字符串会出错 
  4.  * :正确创建对象 
  5.  *  
  6.  * @author xuzhaohu 
  7.  *  
  8.  */  
  9. public class UsbFactory1 {  
  10.   
  11.     public Usb produce(String type) {  
  12.         if ("phone".equals(type)) {  
  13.             return new Phone();  
  14.         } else if ("camera".equals(type)) {  
  15.             return new Camera();  
  16.         } else {  
  17.             System.out.println("请输入正确的类型!");  
  18.             return null;  
  19.         }  
  20.     }  
  21. }  

子类实例化通过工厂类去创建,如要创建camera,

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. /*普通工厂方法**/  
  2. UsbFactory1 factory1 = new UsbFactory1();  
  3. Usb usb1 = factory1.produce("camera");//+phone  
  4. usb1.store();  

输出:this is Camera usb!

 

总结:实现了工厂模式的基本功能,但是需要传参去控制,会出现很多不确定的问题,可以在工厂类中定义不同产品的生产,就是如下介绍的工厂多方法生产。

(2)工厂多方法

只要在UsbFactory中再定制一下就行,业务更加分明

设计模式-工厂方法模式

根据设计修改工厂类

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. **  
  2.  * 多个工厂类方法  
  3.  *   
  4.  * @author xuzhaohu  
  5.  *   
  6.  */  
  7. public class UsbFactory2 {  
  8.   
  9.     public Usb producePhone() {  
  10.         return new Phone();  
  11.     }  
  12.   
  13.     public Usb produceCamera() {  
  14.         return new Camera();  
  15.     }  
  16.   
  17. }  

同样,要实例化某个子类对象,则可以这样去调用:

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. /*多个工厂方法模式**/  
  2.         UsbFactory2 factory2 = new UsbFactory2();  
  3.         Usb usb2 = factory2.producePhone();//+camera  
  4.         usb2.store();  

输出:this is Phone usb!

这样是不是让业务逻辑更加清晰了一些呢!

但是如果在多处都要调用生产的话,不能每次都通过实例化工厂类然后去生产吧,这时候可以怎么样呢?

对,可以通过类访问,在工厂类中加上static方法。

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. /** 
  2.  * 静态工厂方法 
  3.  * :不需要实例 
  4.  *  
  5.  * @author xuzhaohu 
  6.  *  
  7.  */  
  8. public class UsbFactory3 {  
  9.   
  10.     public static Phone producePhone() {  
  11.         return new Phone();  
  12.     }  
  13.   
  14.     public static Camera produceCamera() {  
  15.         return new Camera();  
  16.     }  
  17. }  

那么这时候可以直接不用实例化工厂类去访问了

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. /*静态工厂方法模式**/  
  2. Usb usb3 = UsbFactory3.producePhone();//+camera  
  3. usb3.store();  

 

输出:this is Phone usb!

这样就更加方便了一些。一般情况下,这样就基本能满足需求了,但是如果现在需求又要增加生产另外一个实现类产品Phone1,这时候肯定需要修改工厂类,在工厂类中增加一个新类型的生产Phone1方法。从设计的角度上讲,可能违背了 闭包(对扩展要开放对修改要关闭) 的设计原则,为了不违背这个原则,可以抽象工厂方法去设计,下面将讲到。

(3)抽象的工厂方法

为了不修改工厂中方法,我们可以对每个产品都创建相应工厂类去实现生产。这时候可以通过一个接口 Provider 去定义生产(produce)这个行为,然后让每个产品的工厂类都实现这个接口。这样如果有新的产品要生产的话只需要先实现一个工厂类就行。如下设计设计模式-工厂方法模式

生产接口Provider

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. /** 
  2.  * 将工厂生产的行为写成接口独立 
  3.  *  
  4.  * @author xuzhaohu 
  5.  *  
  6.  */  
  7. public interface Provider {  
  8.   
  9.     Usb produce();  
  10. }  

每个产品都有自己的工厂

 

PhoneFactory工厂

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. public class PhoneFactory implements Provider {  
  2.   
  3.     @Override  
  4.     public Usb produce() {  
  5.         // TODO Auto-generated method stub  
  6.         return new Phone();  
  7.     }  
  8.   
  9. }  

CameraFactory工厂

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. public class CameraFactory implements Provider {  
  2.   
  3.     @Override  
  4.     public Usb produce() {  
  5.         // TODO Auto-generated method stub  
  6.         return new Camera();  
  7.     }  
  8.   
  9. }  

每一个产品可以根据自己的业务来去工厂生产产品,如要生产Camera

[java]  view plain copy 设计模式-工厂方法模式 设计模式-工厂方法模式
  1. /*抽象工厂方法模式**/  
  2.  /*1.扩展性好,不用修改源代码 
  3.   *2.添加一个实现USB接口的类+一个对应的实现Provider的工厂类**/  
  4.  Provider provider = new CameraFactory();  
  5.  Usb usb4 = provider.produce();  
  6.  usb4.store();  

输出:this is Camera usb!