一、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 packet16: * @return the response to send back17: * @throws UnauthorizedException if the user is not authorized18: */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類型的信息:XIQ和YIQ。就分別有XIQHandler和YIQHandler(IQHandler的子類),來分別實現handleIQ(IQ packet)。XIQHandler處理X類型信息,YIQHandler處理Y類型信息。
IQHandler不管是何種類型信息,它只管調用工廠方法handleIQ(IQ packet),處理該信息,然後返回處理結果。
由此可以看出IQHandler相當於CreatorIQ相當於ProductXIQHandler、YIQHandler相當於ConcreteCreatorXIQ、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 shape18: */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的思想都是類似的,由於業務上存在不同類型的任務,體現在程序上就是要調用不同類型的對象完成同樣的任務。但業務類並不知道由哪種類型的對象,因此需要工廠方法,並且讓子類實現工廠方法,返回特定類型的對象,然後業務類再使用這些對象完成任務。