設計模式-工廠方法模式

android中用到了太多的工廠類,其中有用工廠方法模式的,固然也有不少工廠並非使用工廠方法模式的,只是工具管理類。
今天以ThreadFactory舉例說明一下簡單工廠模式和工廠方法模式。 
工廠方法模式,Factory Method,簡單的方式,不簡單的應用。java

1.意圖
定義一個用於建立對象的接口,讓子類決定實例化哪一個類。工廠方式模式使一個類的實例化延遲到其子類。
熱門詞彙:虛構造器 延遲 建立對象 子類 android

2.結構圖和代碼
咱們先看看標準的工廠方法結構圖:閉包


先抽象的產品類,抽象的工廠類,而後用客戶端具體的工廠生產相應的具體的產品,可是客戶端並不知道具體的產品是怎麼生產的,生產的過程封裝在工廠裏。因此說,某種程度上,工廠方法模式改變了咱們直接用new建立對象的方式,一個很好的開始,意義重大。
以ThreadFactory爲例:app

這張圖其實和本來的結構圖有細微的區別,那就是參數化得工廠,並且從業務意義上也有些不一樣,可是思想是同樣的。
咱們來看下具體的代碼:ide

  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. //同理,咱們能夠建立另外相似的工廠,生產某種專門的線程,很是容易擴展  

看到這裏,咱們一方面爲它的生產便利性感嘆,一方面又爲沒建立某類產品都要建立一個工廠而感到繁瑣,因此咱們下面介紹簡單工廠,它的結構圖以下:oop


簡單工廠把抽象工廠去掉了,你就建立一個專門生產某類產品就好。在一些特定而又不負責的領域很是實用方便套用這個模式。
在android中的Connection類中使用到了這個類:this


其中Connection這個抽象類,既充當抽象產品類,也充當具體工廠類。
由於這種狀況下,咱們每每須要的是立刻生產子類,getConnection方法每每是靜態的,因此簡單工廠,也叫靜態工廠方法。
咱們看看代碼以下:spa

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

這就是簡單工廠,一個很簡單的參數化工廠,真的很簡單。.net

3.效果
1.建立型模式;
2.參數化工廠方法模式獲得相應的對象;
3.爲子類提供掛鉤;
4.鏈接平行的類層次。

另一個例子:

 

先假設要作這樣的一個設計。設計一個Usb功能的接口,具備store(存儲)和takeAlong(攜帶方便)兩個行爲。而後要設計兩個產品,一個是 Phone(手機),另外一個是Camera(照相機),很顯然,它們均可以是 Usb的實現類。爲了便於統一管理和建立,咱們很容易就能設計出一個簡單的工廠模式。

(1)普通的工廠方法

首先,咱們能夠畫出相關的設計圖:

代碼實現以下:

定義Usb接口

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. public interface Usb {  
  2.   
  3.     void store();  
  4.   
  5.     void takeAlong();  
  6. }  

Phone類

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  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 在CODE上查看代碼片 派生到個人代碼片
  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 在CODE上查看代碼片 派生到個人代碼片
  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 在CODE上查看代碼片 派生到個人代碼片
  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 在CODE上查看代碼片 派生到個人代碼片
  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 在CODE上查看代碼片 派生到個人代碼片
  1. /*多個工廠方法模式**/  
  2.         UsbFactory2 factory2 = new UsbFactory2();  
  3.         Usb usb2 = factory2.producePhone();//+camera  
  4.         usb2.store();  

輸出:this is Phone usb!

這樣是否是讓業務邏輯更加清晰了一些呢!

可是若是在多處都要調用生產的話,不能每次都經過實例化工廠類而後去生產吧,這時候能夠怎麼樣呢?

對,能夠經過類訪問,在工廠類中加上static方法。

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  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 在CODE上查看代碼片 派生到個人代碼片
  1. /*靜態工廠方法模式**/  
  2. Usb usb3 = UsbFactory3.producePhone();//+camera  
  3. usb3.store();  

 

輸出:this is Phone usb!

這樣就更加方便了一些。通常狀況下,這樣就基本能知足需求了,可是若是如今需求又要增長生產另一個實現類產品Phone1,這時候確定須要修改工廠類,在工廠類中增長一個新類型的生產Phone1方法。從設計的角度上講,可能違背了 閉包(對擴展要開放對修改要關閉) 的設計原則,爲了避免違背這個原則,能夠抽象工廠方法去設計,下面將講到。

(3)抽象的工廠方法

爲了避免修改工廠中方法,咱們能夠對每一個產品都建立相應工廠類去實現生產。這時候能夠經過一個接口 Provider 去定義生產(produce)這個行爲,而後讓每一個產品的工廠類都實現這個接口。這樣若是有新的產品要生產的話只須要先實現一個工廠類就行。以下設計

生產接口Provider

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. /** 
  2.  * 將工廠生產的行爲寫成接口獨立 
  3.  *  
  4.  * @author xuzhaohu 
  5.  *  
  6.  */  
  7. public interface Provider {  
  8.   
  9.     Usb produce();  
  10. }  

每一個產品都有本身的工廠

 

PhoneFactory工廠

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  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 在CODE上查看代碼片 派生到個人代碼片
  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 在CODE上查看代碼片 派生到個人代碼片
  1. /*抽象工廠方法模式**/  
  2.  /*1.擴展性好,不用修改源代碼 
  3.   *2.添加一個實現USB接口的類+一個對應的實現Provider的工廠類**/  
  4.  Provider provider = new CameraFactory();  
  5.  Usb usb4 = provider.produce();  
  6.  usb4.store();  

輸出:this is Camera usb!

相關文章
相關標籤/搜索