AS2現在可以說是面向對象的,但是它所支持的面向對象特性還是比較簡單的,有些像smalltalk,動態性比c++要強很多,用來實踐設計模式還是綽綽有餘的。
按照書的排布,第一個模式是abstract factory,個人的理解是,客戶只需對工廠發佈命令,具體的實現則由具體的工廠實現,關鍵一點,各個工廠的產品一致,這是一個應用的需求,同時也是她的特點。abstract factory很好的封裝了一系列產品的創建一致性。
在我的例子裏,用了快餐店的例子,McDonald和KFC,都提供了漢堡、可樂、薯條和冰激淋,因此例子中就由他們作爲工廠了。
最開始的是snacketeria快餐店接口,它定義了McDonald和KFC的統一接口函數:
snacketeria.as
interface snacketeria { public function makeHamburg():Hamburg; public function makeFry():Fry; public function makeCola():Cola; public function makeIceCream():IceCream; public function getShopName():String; } |
McDonald.as
class McDonald implements snacketeria { private var _name:String; public function makeHamburg():Hamburg { return new McHamburg(); } public function makeFry():Fry { return new Fry(); } public function makeCola():Cola { return new McCola(); } public function makeIceCream():IceCream { return new IceCream(); } function McDonald() { _name = "McDonald"; } public function getShopName():String { return _name; } } |
kFC.as
class KFC implements snacketeria { private var _name:String; public function makeHamburg():Hamburg { return new KFCHamburg(); } public function makeFry():Fry { return new Fry(); } public function makeCola():Cola { return new KFCCola(); } public function makeIceCream():IceCream { return new IceCream(); } function KFC() { _name = "KFC"; } public function getShopName():String { return _name; } } |
首先是food類,它是所有食物的基類
food.as
class food { private var _name:String; private var _price:Number; private var _discount:Number; private var _type:String; public function set name(Name:String):Void |
他們是不能在類的外部被直接操作的,所以getter/setter可以說沒有用武之地, 還是直接定義setProperty和getProperty函數爲好,
或者我對setter/getter函數的用戶所知不全?)
然後分別是Hamburg漢堡、McHamburg麥當勞的漢堡、KFCHamburg、Cola、McCola、KFCCola、Fry薯條、IceCream這些食品類
Hamburg.as
class Hamburg extends food { function Hamburg() { _name = "漢堡"; _price = 0; _discount = 1; _type = "Hamburg"; } } |
class McHamburg extends Hamburg { function McHamburg() { _name = "超級漢堡"; _price =5.5; _discount = 0.8; _type = "McDonald Hamburg"; } } |
class KFCHamburg extends Hamburg { function KFCHamburg() { _name = "無敵巨無霸"; _price = 10; _discount = 0.9; _type = "KFC Hamburg"; } } |
class Cola extends food { function Cola() { _name = "可樂"; _price = 0; _discount = 1; _type = "Cola"; } } |
class McCola extends Cola { function McCola() { _name = "可口可樂"; _price =2.5; _discount = 1; _type = "McDonald Cola"; } } |
class KFCCola extends Cola { function KFCCola() { _name = "百事可樂"; _price =2.5; _discount = 1; _type = "KFC Cola"; } } |
class Fry extends food { function Fry() { _name = "薯條"; _price = 5; _discount = 1; _type = "Fry"; } } |
冰激淋同樣如是
IceCream.as
class IceCream extends food { function IceCream() { _name = "冰激淋"; _price = 2; _discount = 1; _type = "Ice Cream"; } } |
order.as
class order { private var _foods:Array; private var _price:Number; private var _shop:snacketeria; function order(shop:String) { _foods = new Array(); _price = 0; switch (shop) { case "McDonald": _shop = new McDonald(); break; case "KFC": _shop = new KFC(); break; default: _shop = new snacketeria(); } } public function addFood(item:food,count:Number):Boolean { if (Math.floor(count) >0) { _foods.push({item:item,count:count}); return true; }else return false; } |
var shop:snacketeria = new McDonald();//先確定到哪家店去消費 var lunch:order = new order(shop.getShopName());//開始上午餐了 lunch.addFood(shop.makeHamburg(),3);//三份漢堡 lunch.addFood(shop.makeCola(),2);//兩杯可樂 lunch.addFood(shop.makeIceCream(),2);//兩個icecream lunch.addFood(shop.makeFry(),1);//一份薯條 lunch.getInfo(); |
Your Orders Detail: McDonald Foods: McDonald Hamburg Details: Name:超級漢堡 Price:5.5 Discount:0.8 Count:3 McDonald Cola Details: Name:可口可樂 Price:2.5 Discount:1 Count:2 Ice Cream Details: Name:冰激淋 Price:2 Discount:1 Count:2 Fry Details: Name:薯條 Price:5 Discount:1 Count:1 Total Price:27.2 |
GoF在他們的書中所舉的使用Abstract factory例子是關於界面的,當你要你的程序具有不同的界面風格,如mac、KDE、Windows等等不同的按鈕、滾動條風格,你就可以使用Abstract模式,爲不同的風格設立一個styleFactory,來分別建立不同的button,scrollbar;這個其實在flash程序中也是一個很好的應用,當需要flash具有不同的界面風格時,可以用這種方式。
同時,abstract factory的缺點是:擴展很麻煩。對於我的例子,假如McDonal和KFC同時推出了一款新的食物,例如pizza,那麼我就必須建立三個類,general pizza類,McPizza,KFCPizza類,當然如果兩個店的相同的話,一個類就足夠了,但是還要修改factory的方法,添加makePizza的method,如果有遺漏的話就出問題了,這個是很難保證的。:(
文章出處:AS2實踐設計模式(1):abstract factory模式