工厂模式的起源
1.变化点在“对象的创建”,因此就封装“对象创建”;
2.面向接口编程,依赖接口,而非依赖实现。
动机(Motivation)
在系统中,经常面临着“一系列相互以来的对象”的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种“封装机制”来避免客户程序和这种“多系列具体对象创建工作”的紧耦合?这就是我们要说的抽象工厂模式。
结构(Structure)
实现(Actionscript code)
//抽象工厂(AbstractFactory) package com.rock506.themes.abstract {import flash.errors.IllegalOperationError;public class AbstractThemeFactory{public function createSubmitButton():SubmitButton{throw new IllegalOperationError("abstract method");return null;}public function createCancelButton():CancelButton{throw new IllegalOperationError("abstract method");return null;}public function createMessageBox():MessageBox{throw new IllegalOperationError("abstract method");return null;}} }
//抽象产品A(AbstractProductA) package com.rock506.themes.abstract {import flash.display.Sprite;import flash.errors.IllegalOperationError;public class Panel extends Sprite{public function Panel(){drawSkin();}protected function drawSkin():void{throw new IllegalOperationError("abstract method");}} }
//抽象产品B(AbstractProductB) package com.rock506.themes.abstract {import flash.display.Sprite;import flash.errors.IllegalOperationError;public class SubmitButton extends Sprite{public function SubmitButton() {drawSkin();}protected function drawSkin():void{throw new IllegalOperationError("abstract method");}} }
//具体产品A1(ConcreteProductA1) package com.rock506.themes.win7 {import com.rock506.themes.abstract.Panel;internal class Win7Panel extends Panel{public function Win7Panel(){super();}protected override function drawSkin():void{trace("draw skin: Win7Panel");}} }
//具体产品B1(ConcreteProductB1) package com.rock506.themes.win7 {import com.rock506.themes.abstract.SubmitButton;internal class Win7SubmitButton extends SubmitButton{public function Win7SubmitButton(){super();}protected override function drawSkin():void{trace("draw skin: Win7SubmitButton");}} }
//具体工厂(ConcreteFactory) package com.rock506.themes.win7 {import com.rock506.themes.abstract.*;public class Win7ThemeFactory extends AbstractThemeFactory{public override function createSubmitButton():SubmitButton{return new Win7SubmitButton();}public override function createCancelButton():CancelButton{return new Win7CancelButton();}public override function createMessageBox():MessageBox{return new Win7MessageBox();}} }
//管理器 package com.rock506 {import com.rock506.themes.abstract.AbstractThemeFactory;import com.rock506.themes.abstract.CancelButton;import com.rock506.themes.abstract.Panel;import com.rock506.themes.abstract.SubmitButton;import flash.display.Sprite;public class ThemeManager{private var _theme:AbstractThemeFactory;public function ThemeManager(theme:AbstractThemeFactory){_theme = theme;}public function BuildMessageBox():Sprite{var sp:Sprite = new Sprite();var panel:Panel = _theme.createMessageBox();var submitButton:SubmitButton = _theme.createSubmitButton();var cancelButton:CancelButton = _theme.createCancelButton();sp.addChild(panel);sp.addChild(submitButton);sp.addChild(cancelButton);return sp;}} }
//客户端 //使用xp主题 //var theme:ThemeManager = new ThemeManager(new XpThemeFactory()); //使用win7主题 var theme:ThemeManager = new ThemeManager(new Win7ThemeFactory()); var messageBox:Sprite = theme.BuildMessageBox(); addChild(messageBox);
实现要点(notice)
1.如果没有应对“多系列对象创建”的需求变化,则没有必要使用抽象工厂模式,这时候使用简单的静态工厂完全可以;
2. 系列对象指的是这些对象之间有相互依赖、或作用的关系;
3.抽象工厂模式经常和工厂方法模式共同组合来应对“对象创建”的需求变化;
4.把工厂作为单件,一个应用中一般每个产品系列只需一个具体工厂的实例,因此,工厂通常最好实现为一个单件模式。
参考文献(reference)
《C#面向对象设计模式纵横谈》视频
http://terrylee.cnblogs.com