[轉載]AS2實踐設計模式(1):abstract factory模式

最初的動機還是看到JimLee寫的幾篇關於設計模式的文章,剛好自己這一陣考完了試,現在抽出時間來系統的學習設計模式,所以就用AS2來實踐一下設計模式裏面講述的23個模式了。
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和KFC類,對快餐店接口進行實現:
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
{
_name = Name;
}
public function set price(Price:Number):Void
{
_price = Price;
}
public function set discount(Discount:Number):Void
{
_discount = Discount;
}
public function set type(Type:String):Void
{
_type = Type;
}
public function get name():String
{
return _name;
}
public function get price():Number
{
return _price;
}
public function get discount():Number
{
return _discount;
}
public function get type():String
{
return _type;
}
function food()
{
_name = "General food";
_type = "food";
_price =0;
_discount =1;
}
public function getPrice():Number
{
return _price * _discount;
}
public function getInfo():Void
{
trace(_type +" Details:");
trace("Name:"+ _name);
trace("Price:"+_price);
trace("Discount:"+_discount);
}
}

(現在有一個想法,覺得對於類中的private屬性,沒有必要實現他們的setter/getter,因爲本身作爲private類型,
他們是不能在類的外部被直接操作的,所以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";
}
}
McHamburg.as
class McHamburg extends Hamburg
{
function McHamburg()
{
_name = "超級漢堡";
_price =5.5;
_discount = 0.8;
_type = "McDonald Hamburg";
}
}
KFCHamburg.as
class KFCHamburg extends Hamburg
{
function KFCHamburg()
{
_name = "無敵巨無霸";
_price = 10;
_discount = 0.9;
_type = "KFC Hamburg";
}
}
Cola.as
class Cola extends food
{
function Cola()
{
_name  = "可樂";
_price = 0;
_discount = 1;
_type = "Cola";
}
}
McCola.as
class McCola extends Cola
{
function McCola()
{
_name = "可口可樂";
_price =2.5;
_discount = 1;
_type = "McDonald Cola";
}
}
KFCCola.as
class KFCCola extends Cola
{
function KFCCola()
{
_name = "百事可樂";
_price =2.5;
_discount = 1;
_type = "KFC Cola";
}
}
Fry.as薯條類
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";
}
}
好了,我們的類已經都定義好了,下面就是寫一個例子來client來操作,姑且就稱爲order吧,有少許composite的思想
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;

}
public function getTotal():Number
{
var index:Number = 0;
_price = 0;
for (index =0; index < _foods.length; index++)
{
_price += _foods[index].item.getPrice()*_foods[index].count;
}
return _price;
}
public function getInfo()
{
var index:Number = 0;
trace ("Your Orders Detail:");
trace (_shop.getShopName());
trace ("Foods:");
for (index =0; index < _foods.length; index ++)
{
_foods[index].item.getInfo();
trace ("Count:"+_foods[index].count);
}
trace ("");
trace ("Total Price:"+getTotal());
}
}

接下來創建一個flash,在第一幀輸入下面的代碼進行測試:
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模式
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章