在游戏场景的设计过程中,我们需要很多不同种类的场景,比如iphone上面很经典的一个游戏“忍者跳跃”相信大家都很熟悉吧。在该游戏场景中,有很多种场景,首先我们来考虑游戏中怪物类的设计,游戏开发者设计的类如图01:
在游戏中,需要创建Fox的类,这样就可以使用 Monster monster = new Fox() 这条语句来创建一个怪物的类。程序中所有需要Fox的类都会使用上述的代码进行创建。现在需求有改动,需要将Fox的怪物改成Stone,所有代码中出现 Monster monster = new Fox() 的语句都会相应的转变为 Monster monster = new Stone()。这么做的缺点有很多,首先改动的地方很多,不易完全改完,容易bug,后期的维护会越来越困难。其次,代码进行改动,需要游戏的重新编译部署,这些过程很繁琐,而且比较复杂。
鉴于上面的这么多缺点,于是乎,我们就会自然的想到,不是在代码中进行直接类的调用,而是通过一个函数来返回具体的类,这样,所有的改动都变化为只需要改动函数中的一个小部分,而不是代码中的全部内容。这样类的设计就可以如图02那样的设计。下面是相关实现的代码:
1 public abstract class Monster { 2 } 3 4 public abstract class Fox { 5 } 6 7 public classs MonsterFactory { 8 public static Monster getMonster() { 9 return new Fox(); 10 } 11 } 12 13 Monster monster = MonsterFactory.getMonster();
上述的一个基本实现一般都被称之为静态工厂模式。
现在回到真正的游戏场景中,首先游戏场景中的元素包括:怪物(有比较多种类的小怪物还有一个大Boss),墙(其中包括阻碍物),人物。这些场景是一系列的元素的组合。比如在普通场景中,墙 + 怪物(狐狸、飞鸟、忍者、火龙)+障碍物,这些基本的元素共同组合成一个复杂的场景。如果按照静态工厂模式来进行软件构架的设计,那么就需要很多的辅助类,在代码的编写过程中也需要代码人员去维护一些列的组件,这样的设计对后期的维护可以说是个灾难。在这个案例中,面临的是“一系列相互倚赖对象的变化”,那么在软件的设计中,应该如何进行封装来避免这些多系列对象之间的紧耦合呢?
在《设计模式》那本书中,提供了一种设计模式——抽象工厂模式。
意图:提供一个接口,让接口负责创建一些列相关或者相互倚赖的对象,无需指定具体的类。
结构:
代码事例:
1、场景组件的相关类,对应上述图中的AbstractProuctA,AbstractProuctB这些类。
1 /* 怪物 1 */ 2 public abstract class MonsterOne { 3 public abstract void walk(); 4 public abstract int score(); 5 } 6 7 public class CityAnamial extends MonsterOne { 8 @Override 9 public void walk() {}; 10 11 @Override 12 public int score() {}; 13 } 14 15 /* 怪物 2 */ 16 public abstract class MonsterTwo { 17 public abstract void walk(); 18 public abstract int score(); 19 } 20 21 public class CityStone extends MonsterTwo { 22 @Override 23 public void walk() { }; 24 25 @Override 26 public int score() { }; 27 } 28 29 /* 怪物 3 */ 30 public abstract class MonsterBoss { 31 @Override 32 public abstract void walk() {}; 33 34 @Override 35 public abstract int score() {}; 36 } 37 38 public class CityBoss extends MonsterBoss{ 39 @Override 40 public void walk() { }; 41 42 @Override 43 public int score() { }; 44 } 45 46 /* 墙 */ 47 public abstract class Wall { 48 public abstract void color(); 49 } 50 51 public class CityWall extends Wall { 52 @Override 53 public void color() {}; 54 } 55 56 /* 人物 */ 57 public abstract class Nim { 58 public abstract void run(); 59 } 60 61 public class CityNim extends Nim{ 62 @Override 63 public void run(){}; 64 }
2、对应的抽象工厂类,主要是对应的去创建具体的产品。
1 /* 场景创建的类 */ 2 public abstract class SenceFactory { 3 public abstract MonsterOne createMonsterOne(); 4 public abstract MonsterTwo createMonsterTwo(); 5 public abstract MonsterBoss createMonsterBoss(); 6 public abstract Wall createWall(); 7 public abstract Nim createNim(); 8 } 9 10 /* 城市场景相关组件的创建 */ 11 public class CitySenceFactory extends SenceFactory { 12 @Override 13 public MonsterOne createMonsterOne() { 14 return new CityAnamial(); 15 } 16 17 @Override 18 public MonsterTwo createMonsterTwo() { 19 return new CityStone(); 20 } 21 22 @Override 23 public MonsterBoss createMonsterBoss() { 24 return new CityBoss(); 25 } 26 27 @Override 28 public Wall createWall() { 29 return new CityWall(); 30 } 31 32 @Override 33 public Nim createNim() { 34 return new CityNim(); 35 } 36 }
3、一个简单的使用方法。
1 public class GameManager { 2 SenceFactory secefactory; 3 4 public GameManager(SenceFactory sencefactory) { 5 this.sencefactory = sencefactory; 6 } 7 8 public void buildGame() { 9 MonsterOne monsterone = sencefactory.createMonsterOne(); 10 MonsterTwo monstertwo = sencefactory.createMonsterTwo(); 11 MonsterBoss monsterboss = sencefactory.createMonsterBoss(); 12 Wall wall = sencefactory.createWall(); 13 Nim nim = sencefactory.createNim(); 14 } 15 }
使用总结:
1、如果需求中不需要应对“一系列组件的变化”,就不需要使用抽象工厂模式。
2、“系列对象”指的是这些对象相互作用和相互倚赖的关系,比如游戏开发中的各种物件。
3、 抽象工厂主要应对的是“新系列”需求的变化,无法应对“新的对象”需求的变化。比如在上面的案例中,如果需要在添加一个怪物,这时候抽象工厂的方法就很难应对这种状况。
4、为了解决上述“新需求”的变化,抽象工厂模式经常和工厂方法(Factory Method)结合起来一起使用。
设计模式:03-抽象工厂(Abstract Factory),布布扣,bubuko.com
设计模式:03-抽象工厂(Abstract Factory)
原文:http://www.cnblogs.com/hanzejl/p/3590892.html