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模式