工厂方法解决Client和Product之间的紧耦合。通过把创建对象的过程委托给一个factory。
逻辑模式
Client ---uses----creator-----create---product
OOP的 open-closed思想 opened for extension ,closed for modication
简单工厂 只是属于初级的工厂设计模式。真正的工厂方法 需要用到接口,处理变化的需求非常实用,可以不影响之前已存在的代码。
IProduct 接口
Product1
Product2
AbstractorCreator
公用方法
带参数或者布带参数的工厂方法 fatoryMethod
Creator1
Creator2
Client 调用
工厂方法可以分离对象的创建和使用。减少依赖,降低耦合
软件设计中变化是不可避免的。工厂模式就是在互相依赖的类之间提供一个中间层,防火墙。当然,模式阻止不了类相互依赖,但是可以提供一个可以很好的管理这种依赖的框架。
以下是一个炮弹设计游戏中使用工厂模式的例子。其中炮弹是product,武器是factory可以创建炮弹,飞船携带武器,同时也是product。Client通过ShipCreator创建飞船。
Projectile
View Code
1 package weapons 2 { 3 import flash.display.Sprite; 4 import flash.events.Event; 5 6 /** 7 * ... 8 * @author liuyong 9 */ 10 //抽象类 应该被继承而不能实例化 11 internal class Projectile extends Sprite 12 { 13 internal var nSpeed:Number; //速度 14 //抽象方法必须被子类重写 15 internal function drawProjectile():void { } 16 internal function arm():void { 17 //设置缺省速度 5pixels/per frame 18 nSpeed = 5; 19 } 20 internal function release():void { 21 //关联enterframe事件 doMoveProjectile 22 this.addEventListener(Event.ENTER_FRAME, this.doMoveProjectile); 23 } 24 internal function doMoveProjectile(event:Event):void { 25 this.y += nSpeed;//移动射弹 26 if (this.y < 0 || this.y > this.stage.stageHeight) { 27 //移除事件监听 28 this.removeEventListener(Event.ENTER_FRAME, this.doMoveProjectile); 29 this.stage.removeChild(this); 30 } 31 } 32 internal function setLoc(xLoc:int,yLoc:int):void { 33 this.x = xLoc; 34 this.y = yLoc; 35 } 36 37 } 38 39 }
AlienCannonBall
View Code
1 package weapons 2 { 3 4 /** 5 * ... 6 * @author liuyong 7 */ 8 internal class AlienCannonBall extends Projectile 9 { 10 public function AlienCannonBall() { } 11 override internal function drawProjectile():void 12 { 13 this.graphics.lineStyle(3, 0xFF00FF); 14 this.graphics.drawCircle(0, 0, 5); 15 } 16 override internal function arm():void 17 { 18 this.nSpeed = 8; 19 } 20 } 21 22 }
AlienMine
View Code
1 package weapons 2 { 3 import flash.events.Event; 4 5 /** 6 * ... 7 * @author liuyong 8 */ 9 internal class AlienMine extends Projectile 10 { 11 public function AlienMine() { } 12 override internal function drawProjectile():void 13 { 14 graphics.lineStyle(3, 0xFF0000); 15 graphics.drawRect( -5, -5, 10, 10); 16 graphics.endFill(); 17 } 18 override internal function arm():void 19 { 20 nSpeed = 2; 21 } 22 override internal function doMoveProjectile(event:Event):void 23 { 24 super.doMoveProjectile(event); 25 this.rotation += 5; 26 } 27 } 28 29 }
HeroCannonBall
View Code
1 package weapons 2 { 3 4 /** 5 * ... 6 * @author liuyong 7 */ 8 internal class HeroCannonBall extends Projectile 9 { 10 public function HeroCannonBall() { } 11 override internal function drawProjectile():void 12 { 13 graphics.beginFill(0xFFFF00); 14 graphics.drawCircle(0, 0, 5); 15 graphics.endFill(); 16 } 17 override internal function arm():void 18 { 19 this.nSpeed = -10; 20 } 21 } 22 23 }
AbstractWeapon
View Code
1 package weapons 2 { 3 import flash.display.Stage; 4 import flash.errors.IllegalOperationError; 5 6 /** 7 * ... 8 * @author liuyong 9 */ 10 public class AbstracWeapon 11 { 12 public function fire(cWeapon:int , target:Stage,xLoc:int,yLoc:int ):void { 13 var projectile:Projectile = this.createProjectile(cWeapon); 14 trace("fire" + projectile.toString()) 15 //画炮弹 16 projectile.drawProjectile(); 17 projectile.setLoc (xLoc , yLoc );//设置炮弹初始位置 18 projectile.arm();//装备炮弹 设置速度 19 target.addChild(projectile );//加入到舞台 20 projectile.release();//发射,绑定enterframe的事件处理,移动炮弹即发射 21 } 22 protected function createProjectile(cWeapon:int):Projectile { 23 throw new IllegalOperationError("Abstract Method:must be overridden in a subclass"); 24 return null; 25 } 26 } 27 28 }
HeroWeapon
View Code
1 package weapons 2 { 3 4 /** 5 * ... 6 * @author liuyong 7 */ 8 public class HeroWeapon extends AbstracWeapon 9 { 10 public function HeroWeapon() { } 11 public static const CANNON:uint = 0 ; 12 override protected function createProjectile(cWeapon:int):Projectile 13 { 14 if (cWeapon == CANNON ) { 15 trace("create a hero cannon") 16 return new HeroCannonBall(); 17 }else { 18 throw new Error("Invalid kind of projectile specified"); 19 } 20 } 21 } 22 23 }
AlienWeapon
View Code
1 package weapons 2 { 3 4 /** 5 * ... 6 * @author liuyong 7 */ 8 public class AlienWeapon extends AbstracWeapon 9 { 10 public static const CANNON:uint = 0 ; 11 public static const MINE:uint = 1; 12 public function AlienWeapon() { } 13 override protected function createProjectile(cWeapon:int):Projectile 14 { 15 if (cWeapon == CANNON ) { 16 trace("create a alien cannonball") 17 return new AlienCannonBall(); 18 }else if (cWeapon == MINE ) { 19 trace("create a alien mine") 20 return new AlienMine(); 21 }else { 22 throw new Error("Invalid kind of projectile specified"); 23 return null; 24 } 25 } 26 } 27 28 }
Ship
View Code
1 package ships 2 { 3 import flash.display.Sprite; 4 5 /** 6 * ... 7 * @author liuyong 8 */ 9 //抽象类 默认是实现方法 和两个抽象方法 10 internal class Ship extends Sprite 11 { 12 public function Ship() { } 13 internal function setLoc(xLoc:int,yLoc:int):void { 14 this.x = xLoc; 15 this.y = yLoc; 16 } 17 internal function drawShip():void { 18 19 } 20 //抽象飞船的行为 21 internal function initShip():void{} 22 23 } 24 25 }
HeroShip
View Code
1 package ships 2 { 3 import flash.events.MouseEvent; 4 import weapons.HeroWeapon; 5 6 /** 7 * ... 8 * @author liuyong 9 */ 10 internal class HeroShip extends Ship 11 { 12 private var weapon:HeroWeapon; 13 public function HeroShip() { } 14 override internal function drawShip():void 15 { 16 graphics.beginFill(0x00FF00); // green color 17 graphics.drawRect(-5, -15, 10, 10); 18 graphics.drawRect(-12, -5, 24, 10); 19 graphics.drawRect(-20, 5, 40, 10); 20 graphics.endFill( ); 21 } 22 override internal function initShip():void 23 { 24 weapon = new HeroWeapon(); 25 //监听鼠标移动事件 移动飞船 监听MouseDown,发射 26 this.stage.addEventListener(MouseEvent.MOUSE_MOVE, doMoveShip); 27 this.stage.addEventListener (MouseEvent.MOUSE_DOWN, doFire); 28 } 29 protected function doMoveShip(event:MouseEvent):void { 30 this.x = event.stageX; 31 event.updateAfterEvent(); 32 } 33 protected function doFire(event:MouseEvent):void { 34 weapon.fire(HeroWeapon.CANNON , this.stage, this.x, this.y - 15); 35 event.updateAfterEvent();//process the event first 先处理此事件 36 } 37 } 38 39 }
AlienShip
View Code
1 package ships 2 { 3 import flash.events.Event; 4 import weapons.AlienWeapon; 5 6 /** 7 * ... 8 * @author liuyong 9 */ 10 internal class AlienShip extends Ship 11 { 12 private var weapon:AlienWeapon; 13 private const aProjectiles:Array = [AlienWeapon.CANNON,AlienWeapon.MINE]; 14 public function AlienShip() { } 15 override internal function drawShip():void 16 { 17 graphics.beginFill(0xFFFFFF); // white color 18 graphics.drawRect(-5, -10, 10, 5); 19 graphics.drawRect(-20, -5, 40, 10); 20 graphics.drawRect(-20, 5, 10, 5); 21 graphics.drawRect(10, 5, 10, 5); 22 graphics.endFill( ); 23 } 24 override internal function initShip():void 25 { 26 weapon = new AlienWeapon(); 27 //绑定doFire方法到舞台的enterframe事件中 28 this.stage.addEventListener(Event.ENTER_FRAME, doFire); 29 } 30 protected function doFire(event:Event):void { 31 //fire randomly 4% chance of firing on each enterframe 32 if (Math.ceil(Math.random()*25)==1) { 33 //随机产生一枚炮弹 34 var cWeapon:uint = aProjectiles[Math.floor(Math.random() * aProjectiles.length)]; 35 weapon.fire(cWeapon , this.stage, this.x, this.y + 15); 36 } 37 } 38 } 39 40 }
ShipCreator
View Code
1 package ships 2 { 3 import flash.display.Stage; 4 /** 5 * ... 6 * @author liuyong 7 */ 8 public class ShipCreator 9 { 10 public static const HERO:uint = 0 ; 11 public static const ALIEN:uint = 1; 12 public function ShipCreator() 13 { 14 15 } 16 17 public function addShip(shipType:uint , target:Stage,xLoc:int,yLoc:int ):void { 18 var ship:Ship = this.createShip(shipType); 19 ship.drawShip(); 20 target.addChild(ship); 21 ship.setLoc(xLoc, yLoc ); 22 ship.initShip(); 23 } 24 protected function createShip(shipType:uint):Ship { 25 if (shipType == HERO ) { 26 return new HeroShip(); 27 }else if (shipType == ALIEN) { 28 return new AlienShip(); 29 }else { 30 throw new Error("Invalid kind of ship specified"); 31 return null; 32 } 33 } 34 35 } 36 37 }
Main
View Code
1 package 2 { 3 import flash.display.Sprite; 4 import flash.events.Event; 5 import ships.ShipCreator; 6 7 /** 8 * ... 9 * @author liuyong 10 */ 11 [Frame(factoryClass="Preloader")] 12 public class Main extends Sprite 13 { 14 private var shipeCreator:ShipCreator = new ShipCreator(); 15 public function Main():void 16 { 17 if (stage) init(); 18 else addEventListener(Event.ADDED_TO_STAGE, init); 19 } 20 21 private function init(e:Event = null):void 22 { 23 removeEventListener(Event.ADDED_TO_STAGE, init); 24 // entry point 25 //增加英雄船 26 shipeCreator.addShip(ShipCreator.HERO, this.stage, this.stage.width / 2, this.stage.height - 20); 27 //增加外星船 28 for (var i:Number = 0 ; i < 5; i++ ) { 29 shipeCreator.addShip(ShipCreator.ALIEN, this.stage, 30 120 + 80 * i, 100); 31 } 32 } 33 34 } 35 36 }