工廠方法模式和IoC/DI的實際應用——AndroidPN和俄羅斯方塊

一、AndroidPn——IQHandler

在學習工廠方法模式的時候,看到實例代碼,感覺以前就見過這種模式的應用。原來,前不久做的有關AndroidPn的項目中,服務器有段代碼的形式和工廠方法很相似。

之前,在這篇文章《模擬AndroidPN Client(1)——AndroidPN源碼簡析》中分析瞭如何在服務器中處理自定義的xmpp節。

IQHandler處理信息<iq>節的抽象類,註冊IQHandler就是繼承IQHandler,重寫其中的handleIQ(IQ)方法返回應答的<iq>節.

IQHandler的process(IQ)即是處理各種IQ,在實際過程中是IQHandler handler = new IQXXXHandler()。在調用

handler.process()就會調用子類的handleIQ(IQ)方法

再看看代碼是如何實現的

   1: public abstract class IQHandler {
   2:  
   3:     //爲了代碼簡潔,刪除了try...catch和其餘的方法
   4:     public void process(Packet packet) {
   5:         IQ iq = (IQ) packet;
   6:         IQ reply = handleIQ(iq);
   7:         if (reply != null) {
   8:             PacketDeliverer.deliver(reply);
   9:         }
  10:     }
  11:  
  12:     /**
  13:      * Handles the received IQ packet.
  14:      * 
  15:      * @param packet the packet
  16:      * @return the response to send back
  17:      * @throws UnauthorizedException if the user is not authorized
  18:      */
  19:     public abstract IQ handleIQ(IQ packet) throws UnauthorizedException;
  20: }
注意紅色的代碼
IQ reply = handleIQ(iq);
public abstract IQ handleIQ(IQ packet) throws UnauthorizedException;
不正好和《工廠方法模式》所演示的例子很像嗎?
1.首先,業務類(IQHandler)事先是不可能知道客戶端會發送什麼類型的消息,也就是說IQHandler根本就不應該和具體的消息類(繼承抽象類IQ)耦合在一起。
 
2.然而,IQHandler是用來處理客戶端發送來的信息,卻又不能和具體的信息類型耦合。這時就能用工廠方法模式,業務類(IQHandler)調用工廠方法 public abstract IQ handleIQ(IQ packet),該方法是抽象類型的,具體由子類去實現。
也就是說,比如有X和Y類型的信息:XIQYIQ就分別有XIQHandlerYIQHandler(IQHandler的子類)來分別實現handleIQ(IQ packet)。XIQHandler處理X類型信息,YIQHandler處理Y類型信息。
 
IQHandler不管是何種類型信息,它只管調用工廠方法handleIQ(IQ packet),處理該信息,然後返回處理結果。
由此可以看出
IQHandler相當於Creator
IQ相當於Product
XIQHandler、YIQHandler相當於ConcreteCreator
XIQ、YIQ相當於ConcreteProduct
 
 
二、俄羅斯方塊——方塊類
Ioc/DI不多作解釋,主要就是應用程序不在主動,而是被動等待容器來注入資源。
1.根據面向對象的思想分析俄羅斯方塊,可知遊戲中下落的每個方法都是一個特定方塊類(正方形、長條等等)的實例。這些方塊都有一個相同的行爲——翻轉。
2.在程序中,每個方塊對象都是由一個二維數組來表示的,所以方塊翻轉時,會因方塊類型的不同,所對應的二維數組也會不同。
 
補充:這裏在簡介二位數組表示方塊的形式。雖然每種類型的方法翻轉樣式不同,但其翻轉樣式是可以事先定義好的。無非就是四個不同的二維數組。
但方塊類事先不知道,遊戲中會產生哪一種類型的方塊(隨機產生),需要等待容器注入特定類型的方塊資源。這就要用到IoC/DI。
方塊類
   1: public abstract class Shape {
   2:     //方塊的二維數組表示形式,有4種形式,所以用一個三維數組表示
   3:     protected int[][][] allShape = new int[4][][];
   4:     //方塊的當前狀態,是二維數組的哪種形式
   5:     private int status;
   6:     
   7:     /**
   8:      * 方塊翻轉
   9:      */
  10:     public void rorate(){
  11:         status++;
  12:         drawShape(allShape[status]);
  13:     }
  14:     
  15:     /**
  16:      * 畫出方塊
  17:      * @param shape
  18:      */

19: public void drawShape(int[][] shape){

//根據二維數組所表示的方塊,畫出該方塊

  21:     }
  20:      
  22:     
  23:     /**
  24:      * 注入特定類型的方塊資源
  25:      * 實際上就是工廠方法
  26:      */
  27:     public abstract void createShape();
  28: }
特定方塊類(Shape的子類)
   1: public class SquareShapre extends Shape {
   2:  
   3:     @Override
   4:     public void createShape() {
   5:         allShape = new int[4][][];
   6:         //定義好方塊的四種形式 ......
   7:     }
   8:  
   9: }

 

Shape只管方塊的翻轉行爲,至於什麼樣的方塊由外部注入。注入哪種方塊由子類完成。比如要注入方形方塊,就由SquareShape類來完成資源(二維數組)注入。

 

工廠方法模式和IoC/DI的思想都是類似的,由於業務上存在不同類型的任務,體現在程序上就是要調用不同類型的對象完成同樣的任務。但業務類並不知道由哪種類型的對象,因此需要工廠方法,並且讓子類實現工廠方法,返回特定類型的對象,然後業務類再使用這些對象完成任務。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章