奇幻RPG(人物构造 与 Abstract Factory模式)
rpgmaker 拼接规则

rpgmaker 拼接规则【实用版】目录1.RPG Maker 简介2.RPG Maker 的拼接规则3.实际应用案例4.总结正文1.RPG Maker 简介RPG Maker,全称"Role-Playing Game Maker",是一款用于制作角色扮演游戏(RPG)的软件。
通过这款软件,用户可以轻松地创建属于自己的 RPG 游戏,无需编程基础。
RPG Maker 提供了丰富的素材、场景、事件和角色,以及灵活的拼接规则,让游戏制作变得更加简单。
2.RPG Maker 的拼接规则RPG Maker 的拼接规则是指在游戏中,如何将不同的素材、场景和事件拼接在一起,形成一个完整的游戏流程。
RPG Maker 采用了一种基于事件的编程方式,用户只需要在事件编辑器中设置各个事件的触发条件和执行动作,即可实现游戏流程的拼接。
具体来说,RPG Maker 的拼接规则包括以下几个方面:(1)地图拼接:通过地图编辑器创建游戏世界,将不同的地图拼接在一起,形成一个完整的游戏地图。
(2)场景拼接:在地图中设置不同的场景,如村庄、森林、山洞等。
通过设置场景的触发条件和执行动作,实现场景之间的切换。
(3)事件拼接:在游戏中设置各种事件,如对话、战斗、收集物品等。
通过设置事件的触发条件和执行动作,实现游戏流程的推进。
(4)角色拼接:创建不同的角色,设置角色的属性、技能和行动模式。
通过设置角色的互动和战斗系统,实现游戏的角色扮演。
3.实际应用案例以一个简单的 RPG 游戏为例,我们可以通过 RPG Maker 的拼接规则,轻松地完成游戏制作。
首先,我们需要创建一个游戏地图,包括村庄、森林和山洞等地图。
然后,在各个地图中设置触发条件和执行动作,实现场景之间的切换。
接下来,我们需要创建主角和敌人角色,设置属性、技能和行动模式。
最后,在游戏中设置对话、战斗和收集物品等事件,完成游戏流程。
4.总结RPG Maker 的拼接规则为用户提供了一个简单易用的游戏制作平台,让游戏制作变得更加轻松。
简单工厂模式——女娲造人

简单⼯⼚模式——⼥娲造⼈1、题⽬:使⽤简单⼯⼚模式模拟⼥娲(Nvwa)造⼈(Person),如果传⼊参数M,则返回⼀个Man对象,如果传⼊参数W,则返回⼀个Woman对象,如果传⼊参数R,则返回⼀个Robot对象。
请⽤程序设计实现上述场景。
2、类图:3、代码:1、抽象产品类–⼈类:package tutorial2;public abstract class Person {public void live() {}public void play() {}}2、具体产品类–男⼈类:package tutorial2;public class Man extends Person {@Overridepublic void live() {System.out.println("⼥娲造⼈————男⼈");super.live();}public void play() {System.out.println("男⼈玩耍中.....");super.play();}}3、具体产品类–⼥⼈类:package tutorial2;public class Woman extends Person {@Overridepublic void live() {System.out.println("⼥娲造⼈————⼥⼈"); super.live();}public void play() {System.out.println("⼥⼈玩耍中.....");super.play();}}4、具体产品类–机器⼈类:package tutorial2;public class Robot extends Person{@Overridepublic void live() {System.out.println("⼥娲造⼈————机器⼈"); super.live();}public void play() {System.out.println("机器⼈玩耍中.....");super.play();}}5、⼯⼚类–⼥娲类:package tutorial2;public class NvWa {public static Person getPerson(String people){ Person person=null ;if(people.equalsIgnoreCase("M")){person = new Man();}else if(people.equalsIgnoreCase("W")){person = new Woman();}else if(people.equalsIgnoreCase("R")){person = new Robot();}return person;}}6、⼥娲造⼈的测试:package tutorial2;public class NvWaMakePeople {public static void main(String[] args) {Person Person;Person = NvWa.getPerson("M"); //⼥娲造男⼈ Person.live();Person.play();System.out.println("**********************");Person = NvWa.getPerson("W"); //⼥娲造⼥⼈ Person.live();Person.play();System.out.println("**********************");Person = NvWa.getPerson("R"); //⼥娲造机器⼈ Person.live();Person.play();}}4、结果。
角色扮演类游戏的名词解释

角色扮演类游戏的名词解释在当今数字化时代,电子游戏已成为人们娱乐生活中不可或缺的一部分。
其中,角色扮演类游戏(RPG)在游戏爱好者中间享有广泛的声誉。
本文旨在解释角色扮演类游戏的相关名词,深入探讨其不同元素和玩法,以及这种游戏类型所带来的愉悦和挑战。
1. 剧情构建角色扮演类游戏通常以一个完整的剧情故事为基础。
玩家在游戏中扮演一个虚拟角色,通过完成游戏中的任务、追寻线索和参与对话,逐步推进剧情的发展。
这种方式使得玩家可以沉浸在游戏的故事情节中,感受到角色的成长和情感变化,提高游戏的代入感和互动性。
2. 角色设定在角色扮演类游戏中,玩家可以自由选择或自定义自己的角色。
这个角色可以是一个勇敢的战士、一个神秘的法师、一个敏捷的刺客,或者其他不同职业和种族的组合。
每个角色都有独特的技能和能力,对游戏的进行起到关键性作用。
3. 角色发展在游戏过程中,角色的发展是非常重要的。
玩家可以通过完成任务、击败敌人、探索世界等方式获得经验值和奖励,进而提升角色的等级和技能。
这种逐步提升的机制激励着玩家继续努力,不断发展和完善自己的角色。
4. 交互系统角色扮演类游戏通常具备丰富的交互系统。
玩家与游戏中的NPC(非玩家角色)进行对话,接受任务、了解情节发展等。
此外,玩家还可以与其他真实玩家进行互动,组队合作、交易物品、共同探索游戏世界。
这种社交性元素使得游戏不再是单纯的个人体验,而是真正的互动体验。
5. 开放世界角色扮演类游戏往往提供一个广阔的开放世界供玩家探索。
这个世界中包含各种城市、地下洞穴、山脉、河流等等,玩家可以自由地冒险和探索。
开放世界给予玩家自由度和探索的乐趣,同时也带来了丰富的任务和挑战。
6. 战斗系统角色扮演类游戏的战斗系统也是游戏的重要组成部分。
玩家可以与敌人进行战斗,并使用自己的技能和装备来击败对手。
这种实时战斗或回合制战斗的机制,使得玩家需要谨慎地选择战术和策略,才能在战斗中获得胜利。
总的来说,角色扮演类游戏为玩家提供了一个沉浸式的虚拟世界,玩家可以在游戏中扮演一个虚拟角色,体验各种冒险、战斗和成长的乐趣。
oop的三种设计模式(单例、工厂、策略)

oop的三种设计模式(单例、⼯⼚、策略)单例模式:废话不多说,我们直接上代码:<?php/**三私⼀公*私有的静态属性:保存类的单例*私有的__construct():阻⽌在类的外部实例化*私有的__clone():阻⽌在类的外部clone对象*共有的静态⽅法:获取类的单例*/class DanLi{private static $instance; //保存类的单例private function __construct() { //阻⽌在类的外部实例化}private function __clone() { //阻⽌在类的外部clone对象}//获取当前类的单例public static function getInstance() {if(!self::$instance instanceof self)//$instance中保存的不是MySQLDB类的单例就实例化self::$instance=new self();return self::$instance; //返回单例}}//测试$db1=DanLi::getInstance();$db2=DanLi::getInstance();var_dump($db1,$db2);我们可以看到结果为下图:我们可以看到,结果为:两个实例化出来对象是⼀样的。
这就体现了我们单例的精髓(只能实例化出来⼀个实例,并且不可复制,能够节省系统资源)注意:静态变量上存在内存中的,它不会因为程序执⾏完毕⼆消失,所以我们第⼆次实例化的时候,会检测到instance的存在,因⽽直接返回已经存在的instance实例。
下⾯我们来看⼀下单例的实际运⽤:⽤于数据库连接类,因为是数据库连接,我们没有必要每⼀次操作数据库都进⾏⼀次数据库类的实例化,那样会⼤⼤的消耗系统资源。
所以,我们⽤到了单例模式,代码如下://初始化连接参数private function initParam($config){$this->host=isset($config['host'])?$config['host']:'';$this->port=isset($config['port'])?$config['port']:'3306';$this->user=isset($config['user'])?$config['user']:'';$this->pwd=isset($config['pwd'])?$config['pwd']:'';$this->charset=isset($config['charset'])?$config['charset']:'utf8';$this->dbname=isset($config['dbname'])?$config['dbname']:'';}private function connect(){$this->link=@mysql_connect("{$this->host}:{$this->port}",$this->user,$this->pwd) or die('数据库连接失败');}private function setCharset(){$sql = "set names '{$this->charset}'";$this->query($sql);}private function selectDB(){$sql = "use `{$this->dbname}`";$this->query($sql);}private function __construct($config){$this->initParam($config);$this->connect();$this->setCharset();$this->selectDB();}private function __clone(){}public static function getInstance($config=array()) {if(!self::$instance instanceof self)self::$instance=new self($config);return self::$instance;}public function query($sql){if(!$result=mysql_query($sql,$this->link)){echo 'sql语句执⾏失败<br />';exit;}return $result;}}$config=array('host' => '127.0.0.1','user' => 'root','dbname' => 'accounts'$db = Test::getInstance($config);$sql = "select * from acc_wechat";$info = $db->query($sql);while($rows = mysql_fetch_row($info)){//echo $rows[1].'<br>';//var_dump($rows);echo $rows[0].'-'.$rows[1].'<br />';}var_dump($info);>通过以下代码,我们就⼤体了解了:单例的原理及实际运⽤。
3D动漫游戏设计——人物角色设计毕业论文

3D动漫游戏设计——人物角色设计毕业论文在当今科技高度发达的时代,3D动漫游戏已经成为了许多人生活中的一部分。
而在3D动漫游戏中的人物角色设计更是游戏的灵魂之一、本文旨在探讨如何进行3D动漫游戏人物角色设计,并对其进行深入分析。
首先,3D动漫游戏人物角色设计需要考虑的是游戏的整体风格和氛围。
不同的游戏有着不同的风格,因此角色设计需要与游戏风格相匹配。
例如,如果游戏是一个幻想风格的RPG游戏,那么角色设计可以包括各种奇幻的生物和装备。
而如果游戏是一个科幻题材的FPS游戏,那么角色设计可以包括未来科技感强烈的人物形象。
因此,设计师需要根据游戏的风格和氛围来确定人物角色设计的方向和风格。
其次,在进行3D动漫游戏人物角色设计时,角色个性的塑造是非常重要的。
一个成功的角色设计应该具有与众不同的个性,能够引起玩家的兴趣并与其产生共鸣。
要达到这个目标,设计师需要考虑人物的外貌、性格、经历等方面来塑造角色的独特个性。
例如,一个勇猛无畏的战士角色可以拥有强壮的身体和坚毅的表情,以展示他们的勇气和决心。
另外,通过为角色赋予一些特殊的技能或能力,也可以进一步加强角色的个性和魅力。
此外,3D动漫游戏人物角色设计还需要考虑到游戏的玩家需求。
不同类型的游戏有不同的受众群体,因此设计师需要根据目标玩家群体的喜好和需求来设计人物角色。
例如,如果目标玩家群体是年轻人,那么角色设计可以充满时尚感和流行元素,以吸引他们的注意。
而如果目标玩家群体是成年人,那么角色设计可以更加注重细节和成熟感,以符合他们的口味和期待。
因此,设计师需要通过市场调研和玩家反馈等手段来了解目标玩家群体的需求,并做出相应的设计。
最后,3D动漫游戏人物角色设计还需要考虑到游戏性和互动性。
在游戏中,玩家将与角色进行互动,并通过角色来体验游戏的故事情节和玩法。
因此,设计师需要考虑到角色的姿势、动作和表情等方面,以确保角色在游戏中的表现力和可玩性。
此外,角色设计还需要考虑到角色的技能和能力,并通过技能系统的设计来增强玩家对角色的掌控感和代入感。
JOF设计模式(很实用的)

设计模式之Factory工厂模式定义:提供创建对象的接口.为何使用?工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。
为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑实用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
我们以类Sample为例,如果我们要创建Sample的实例对象:Sample sample=new Sample();可是,实际情况是,通常我们都要在创建sample实例时做点初始化的工作,比如赋值查询数据库等。
首先,我们想到的是,可以使用Sample的构造函数,这样生成实例就写成:Sample sample=new Sample(参数);但是,如果创建sample实例时所做的初始化工作不是象赋值这样简单的事,可能是很长一段代码,如果也写入构造函数中,那你的代码很难看了(就需要Refactor重整)。
为什么说代码很难看,初学者可能没有这种感觉,我们分析如下,初始化工作如果是很长一段代码,说明要做的工作很多,将很多工作装入一个方法中,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有背于Java面向对象的原则,面向对象的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段之间偶合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。
在本例中,首先,我们需要将创建实例的工作与使用实例的工作分开, 也就是说,让创建实例所需要的大量初始化工作从Sample的构造函数中分离出去。
这时我们就需要Factory工厂模式来生成对象了,不能再用上面简单new Sample(参数)。
角色游戏名词解释
角色游戏名词解释什么是角色游戏(RPG)?角色游戏(Role-playing game,简称RPG)是一种电子游戏类型,玩家在游戏中扮演一个虚构角色的角色扮演游戏。
在角色游戏中,玩家通常可以根据自己的偏好选择角色的外貌、性格和技能等。
1. 角色(Character)角色是指玩家在游戏中扮演的虚拟人物。
玩家可以通过选取不同的角色来体验不同的游戏剧情和玩法。
每个角色通常都有自己的特点、技能和属性。
1.1 属性(Attributes)属性是角色在游戏中的基本特征。
它们可能包括力量、敏捷、智力等。
不同的角色属性将影响其在游戏中的战斗力、生存能力和技能发挥。
1.2 技能(Skills)技能是角色在游戏中所具备的特殊能力或行动。
这些技能可以是攻击技能、防御技能、治疗技能等。
玩家需要根据游戏剧情和战斗需求来合理运用角色的技能。
2. 剧情(Storyline)剧情是角色游戏中的故事背景。
它通常包含一个主线故事,玩家需要通过完成任务、解谜或探索来逐步推进剧情发展。
好的剧情设计可以提升玩家的游戏体验,增加游戏的可玩性。
3. 任务(Quests)任务是玩家在游戏中承担的特定目标和挑战。
完成任务通常可以获得经验值、金币、装备等奖励。
任务可以分为主线任务和支线任务,玩家需要根据自己的进度和能力来选择不同的任务。
4. 装备(Equipment)装备是角色在游戏中使用的工具和武器。
不同的装备可以提供不同的属性加成和技能效果。
玩家需要通过击败敌人、完成任务或购买来获得更强大的装备,提升角色的能力。
5. 经验值(Experience Points)经验值是角色游戏中用于衡量角色成长和进步的指标。
玩家通过击败敌人、完成任务等方式可以获取经验值,累积一定的经验后角色将升级,提升属性和解锁新的技能。
6. 多人游戏(Multiplayer)多人游戏是一种角色游戏的模式,允许玩家与其他真实玩家在线上进行合作或对战。
玩家可以组队探险、进行团队副本或互相竞技来增加游戏的社交和娱乐性。
动漫角色扮演的人物塑造与角色设计
动漫角色扮演的人物塑造与角色设计动漫角色扮演(Cosplay)是指通过扮演动漫、游戏、漫画等作品中的角色,展现他们的形象与人物特点。
在动漫角色扮演中,人物塑造与角色设计起着核心的作用。
本文将探讨动漫角色扮演中的人物塑造与角色设计,以及它们对于作品与观众的重要意义。
一、人物塑造人物塑造是指通过各种手法与元素,使动漫角色具备独特的个性与特点。
在人物塑造中,有以下几个关键要素。
1.1 外表形象动漫角色的外表形象是人们最直观的认知方式。
外表形象可以通过服装、发型、体型等方面来表现。
例如,某些角色会使用具有鲜明特色的服装,或者具备特殊发型,以突出他们的个性与身份。
外表形象的设计可以反映角色的属性、背景与特点,使其在观众心中留下深刻的印象。
1.2 内心特质角色的内心特质是塑造角色深度与立体感的重要因素。
通过角色的言行举止、内心独白等方式,展现角色的情感、价值观与心理活动。
内心特质的设计可以使角色更加真实、可信,并与观众建立情感共鸣。
例如,某些角色可能有善良、勇敢或者冷酷的性格特点,这些特质会在故事中得到体现,进而影响观众的情感和态度。
1.3 行为表现角色的行为表现是通过动作、语言、表情等形式来展现的。
行为表现可以使角色更加生动、立体,并传递出角色性格与情感的细微差别。
例如,某些角色可能以幽默风趣的方式表达观点,或者用宽容与善良的行为感染他人。
行为表现的设计既可以体现角色的个性与特点,同时也为观众提供了更多的情感共鸣与参与感。
二、角色设计角色设计是指创意人员在动漫角色扮演中所进行的整体规划与创作。
一个成功的角色设计需要考虑以下几个因素。
2.1 角色设定角色设定包括角色的姓名、年龄、性别、身份背景等。
角色设定的合理性与独特性对于角色的可塑性与可爱度具有决定性影响。
例如,《火影忍者》中的主角漩涡鸣人,他的设计让观众能够轻松地记住他的名字,并与他建立起情感联系。
2.2 角色关系角色关系指的是角色之间的相互关联与作用。
简单工厂(SimplePattern)模式
简单⼯⼚(SimplePattern)模式⼀、简单⼯⼚(Simple Factory)模式Simple Factory 模式根据提供给它的数据,返回⼏个可能类中的⼀个类的实例。
通常它返回的类都有⼀个公共的⽗类和公共的⽅法。
Simple Factory 模式实际上不是 Gof 23个设计模式中的⼀员。
⼆、简单⼯⼚(Simple Factory)模式⾓⾊与结构⼯⼚类⾓⾊Creator (LightSimpleFactory):⼯⼚类在客户端的直接控制下(Create⽅法)创建产品对象。
抽象产品⾓⾊Product (Light):定义简单⼯⼚创建的对象的⽗类或它们共同拥有的接⼝。
可以是⼀个类、抽象类或接⼝。
具体产品⾓⾊ ConcreteProduct (BulbLight, TubeLight):定义⼯⼚具体加⼯出的对象。
三、简单⼯⼚(Simple Factory)模式演化1) Simple Factory 模式演化(⼀)除了上⾯的⽤法外,在有些情况下Simple Factory可以有抽象产品⾓⾊扮演,⼀个抽象产品类同时是⼦类的⼯⼚。
2) Simple Factory 模式演化(⼆)三个⾓⾊全部合并:与单例模式(Singleton)相近,但是有区别。
四、有点与缺点优点: ⼯⼚类含有必要的判断逻辑,可以决定什么时候创建哪⼀个产品类的实例,客户端可以免除直接创建产品对象的责任,⽽仅仅“消费”产品。
简单⼯⼚模式通过这种做法实现了对责任的分割。
缺点: 当产品有复杂的多层等级结构时,⼯⼚类只有⾃⼰,以不变应万变,就是模式的缺点。
因为⼯⼚类集中了所有产品创建逻辑,⼀旦不能正常⼯作,整个系统都要受到影响。
同时,系统扩展困难,⼀旦添加新产品就不得不修改⼯⼚逻辑,有可能造成⼯⼚逻辑过于复杂。
另外,简单⼯⼚模式通常使⽤静态⼯⼚⽅法,这使得⽆法有⼦类继承,造成⼯⼚⾓⾊⽆法形成基于继承的等级结构。
RPG游戏设计的关键要素
RPG游戏设计的关键要素随着游戏产业的不断发展,RPG游戏成为了一个日渐盛行的游戏类型。
一款优秀的RPG游戏不仅仅是能够为玩家带来娱乐,更需要在游戏设计方面注入灵魂,让玩家能够沉浸其中,体验到一场精彩的冒险之旅。
本文将以最受玩家欢迎的RPG游戏《上古卷轴5》为例,探讨RPG游戏设计的关键要素。
1. 剧情设计一款RPG游戏最重要的要素在于其故事情节的设计。
要让玩家沉浸到游戏中,需要一个引人入胜的故事情节。
《上古卷轴5》的故事设定在一个充满魔法、龙、神秘的世界中,玩家扮演一位龙裔,面对着世界的毁灭。
游戏中不仅充满了奇幻的元素,还有着打动人心的情感的描写,在整个游戏过程中,让玩家深陷其中,随着任务的推进,不断发掘新的秘密。
2. 角色设计角色的设计关系到玩家是否能够真正的沉浸在游戏中。
在《上古卷轴5》中,玩家可以自由选择自己的职业、能力、外貌等,不同的角色特点会让玩家体验到完全不同的游戏体验。
比如,选择一个高智商但体质较弱的法师,在游戏中需要更加谨慎地安排战斗方式,而选择一个力量强大的战士,则可以更加放心大胆的进攻。
3. 游戏场景游戏场景是影响游戏氛围最重要的要素之一。
《上古卷轴5》的游戏场景可以说是无穷无尽,由于游戏的舞台是整个世界,所以玩家可以去到各个地方,体验到不同的环境。
比如,草原、雪山、沙漠、盗墓、沉船等,每个地方都有其独特的环境和气氛,让玩家更加真实的感受到游戏中的世界。
4. 道具系统道具系统是许多RPG游戏中不可或缺的要素,它可以让玩家在游戏中拥有更多的强大武器,同时也可以让玩家更好地实现游戏目标。
在《上古卷轴5》中,玩家可以通过打怪、任务、商店等途径获得不同的装备道具,这些道具不仅可以让玩家更容易地战胜敌人,还可以让玩家不断提升自己的属性和装备。
5. 任务系统RPG游戏中的任务系统是使玩家保持游戏兴趣的关键之一。
在《上古卷轴5》中,任务系统设计得十分周密,玩家可以从各种NPC处接到不同的任务,每个任务都有其独特的目标和奖励。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
引言 在前一节,我们介绍了Strategy模式,并使用此模式实现了一个根据角色的职业来分配技能的范例(实际也就是动态地为类分配方法)。作为一款奇幻RPG,有了职业,我们还应当可以为角色选择种族,比如说:人类(Human)、精灵(Elf)、矮人(Dwarf)、兽人(Orc)等等。而这四个种族又有着截然不同的外形,精灵皮肤灰白、有着长长的耳朵、没有体毛和胡须;矮人的皮肤与人类近似,但是身材矮小、通常留着浓密的胡子;兽人则有着绿色的皮肤和高大的身躯,并且面目丑陋。本文将讨论如何使用GOF的Abstract Factory抽象工厂来实现这样的角色外形设计。
面向实现的方式 简单起见,我们假设角色身体由三部分构成,分别是:头(Head)、身材(Stature)、皮肤(Skin)。那么对于人类的构造,我们的第一反应自然而然地想到:它应当由 HumanHead、HumanStature、HumanSkin三个类复合而成。对于精灵也是类似的设计,于是,我们实现了下面这样的设计(本文将仅以人类和精灵为例介绍):
抽象组成身体的实体类 我们发现这样做,每个角色与他的身体部件是牢牢绑定在一起的,每创建一个角色,我们都需要为它先行创建所有其复合的类(组成身体的实体类(Concret Class),比如HumanHead)。按照面向对象的思想,我们想到应该对这一过程进行封装,将创建角色部件这件事委派给其他的类来完成。观察上图,我们发现尽管角色不同,但它们都是由三个部分构成,所以,我们所能想到的实现这一过程的第一步,就是对组成身体的实体类进行抽象,我们定义三个接口:Head、Stature、Skin,代表身体的三个部分,并且让Human和Elf的实体类去实现这个接口:
观察上图,我们发现尽管定义了接口,但是如果角色Human和Elf仍然与接口的实体类关联,那么效果与面向实现完全相同。现在,是时候对设计做些改动,我们让Human和Elf与接口关联,而不是与接口的实现关联(OO思想:面向接口编程,而不是面向实现编程)。这一次,我们的设计变成下图: 一眼望去,我们发现的第一个问题就是:Human与Elf惊人地相似,再仔细看看,我们注意到它们除了名字不同其余的完全一样。我们不禁思考:有必要把两个完全一样的类起两个名字分别保存么?答案是没有必要,我们将它们合并成一个类,起名叫Race,设计再次变成下面这样: 创建工厂类
看到这里,我们可能会想:现在结构似乎已经很完善了,我们定义了接口来解决问题,也没有为不同的角色创建多个不同的类,而只要在Race的构造函数中为代表身体部件的变量赋不同的值,就可以创建不同种族的角色。好的,那么我们来看看如果要创建一个Human 代码需要如何编写:
Head head = new HumanHead(); Stature stature = new HumanStature(); Skin skin = new HumanSkin(); Race human = new Race(head, stature, skin); 而Race的构造函数是这样的: public Race(head, stature, skin){ this.head = head; this.stature = stature; this.skin = skin; }
我们看到,仅仅创建一个类这样似乎太麻烦了,而且身体的部分类是角色的组成部分,为什么它们要先于角色创建呢?
这时候,我们想到如果有一个类可以专门负责创建身体部件这件事,当我们想要创建角色的时候,将这个类传递给Race的构造函数就可以了。我们管创建Human身体组成部分的类称作:HumanPartsFactory,创建Elf身体部分的类称作ElfPartsFacotry。那么它们应该是这样的:
现在,我们再要创建一个Human,代码变成了这样: HumanPartsFactory humanFactory = new HumanPartsFactory(); Race Human = new Race(humanFactory);
相应的,我们的构造函数也需要改一改: public Race(HumanPartsFactory humanFacotry){ head = humanFactory.CreateHead(); stature = humanFactory.CreateStature(); skin = humanFactory.CreateSkin(); }
一切似乎都很好,直到我们需要创建一个Elf的时候... 我们发现Race的构造函数只能接受一个HumanPartsFactory类型的参数,为了传递ElfPartsFactory,我们将不得不再添加一个接受ElfPartsFactory类型的构造函数。这样显然不好,这一次,有了之前的经验,我们知道我们可以通过同样的方法来解决。
看到这里,你是否能够体会到一些“面向接口”编程的意味?注意到RacePartsFactory,它内部的方法返回的都是接口类型,而其实体子类的方法返回的都是接口的实体类。如果我们之前不声明那看似无用的接口,这里是无法实现的。
现在,我们再次修改Race的构造函数: public Race(RacePartsFactory raceFacotry){ head = raceFacotry.CreateHead(); stature = raceFacotry.CreateStature(); skin = raceFacotry.CreateSkin(); }
当我们需要一个Human的时候: RacePartsFactory humanFactory = new HumanPartsFactory(); Race human = new Race(humanFactory);
当我们需要一个Elf的时候: RacePartsFactory elfFactory = new ElfPartsFactory(); Race elf = new Race(elfFactory);
Abstract Factory设计模式 上面做的这些,使我们又完成了一个设计模式:Abstract Factory。它的正式定义是这样的:提供一个接口用于创建一系列相互关联或者相互依赖的对象,而不需要指定它们的实体类。
下面是本例中 Abstract Factory模式的最终图: 代码实现和测试 using System; using System.Collections.Generic; using System.Text;
namespace AbstractFactory { // 定义构成身体部分的接口 public interface IHead { string name { get;} } public interface IStature { string name { get;} } public interface ISkin { string name { get;} }
// 组成 Human 的类 public class HumanHead : IHead { public string name { get { return "Human Head"; } } } public class HumanStature : IStature { public string name { get { return "Human Stature"; } } } public class HumanSkin : ISkin { public string name { get { return "Human Skin"; } } }
// 组成 Elf 的类 public class ElfHead : IHead { public string name { get { return "Elf Head"; } } } public class ElfStature : IStature { public string name { get { return "Elf Stature"; } } } public class ElfSkin : ISkin { public string name { get { return "Elf Skin"; } } } // 定义工厂接口 public interface IRacePartsFactory { IHead CreateHead(); ISkin CreateSkin(); IStature CreateStature(); }
// 定义Human身体的工厂类 public class HumanPartsFactory : IRacePartsFactory { public IHead CreateHead() { return new HumanHead(); } public IStature CreateStature() { return new HumanStature(); } public ISkin CreateSkin() { return new HumanSkin(); } }
// 定义Elf身体的工厂类 public class ElfPartsFactory : IRacePartsFactory { public IHead CreateHead() { return new ElfHead(); } public IStature CreateStature() { return new ElfStature(); } public ISkin CreateSkin() { return new ElfSkin();