zoukankan      html  css  js  c++  java
  • 设计模式-工厂方法模式

    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接口

    1. public interface Usb {  
    2.   
    3.     void store();  
    4.   
    5.     void takeAlong();  
    6. }  

    Phone类

    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类

    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,负责生产

    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,

    1. /*普通工厂方法**/  
    2. UsbFactory1 factory1 = new UsbFactory1();  
    3. Usb usb1 = factory1.produce("camera");//+phone  
    4. usb1.store();  

    输出:this is Camera usb!

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

    (2)工厂多方法

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

    根据设计修改工厂类

    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. }  

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

    1. /*多个工厂方法模式**/  
    2.         UsbFactory2 factory2 = new UsbFactory2();  
    3.         Usb usb2 = factory2.producePhone();//+camera  
    4.         usb2.store();  

    输出:this is Phone usb!

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

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

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

    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. }  

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

    1. /*静态工厂方法模式**/  
    2. Usb usb3 = UsbFactory3.producePhone();//+camera  
    3. usb3.store();  

    输出:this is Phone usb!

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

    (3)抽象的工厂方法

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

    生产接口Provider

    1. /** 
    2.  * 将工厂生产的行为写成接口独立 
    3.  *  
    4.  * @author xuzhaohu 
    5.  *  
    6.  */  
    7. public interface Provider {  
    8.   
    9.     Usb produce();  
    10. }  

    每个产品都有自己的工厂

    PhoneFactory工厂

    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工厂

    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

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

    输出:this is Camera usb!

  • 相关阅读:
    Jboss下jaxws的开发
    Jboss as 服务器基本设置
    classloader常见问题总结
    Servlet容器 Jetty
    Jetty 的工作原理以及与 Tomcat 的比较
    resin设置jvm参数
    Solr4.0使用
    Solr 4.0部署
    Solr 搜索功能使用
    HttpSolrServer 实例管理参考,来自org.eclipse.smila.solr
  • 原文地址:https://www.cnblogs.com/wangzehuaw/p/4760133.html
Copyright © 2011-2022 走看看