设计模式之原型模式解决魔兽怪物创建(Darren)
来源:互联网 发布:手机分享网络给电脑 编辑:程序博客网 时间:2024/04/30 16:05
在之前的文章中我们讲了简单工厂模式,策略模式,单一职责原则,开放封闭原则,依赖倒转原则,装饰模式,代理模式,抽象工厂模式,上一节在抽象工程模式中讲了利用工厂模式创建英雄的过程,今天我将带大家用原型模式模拟一下魔兽世界里面的怪物创建,其实我平时很少玩游戏的,但是我喜欢对游戏进行分析,下面就讲一下设计思路:
我要模拟的是这样的场景,模拟游戏地图中的出怪功能:
地图中创建怪,也许一次不止要创建一个怪,而是创建一批怪,怎么编程才能让我们的游戏耗的资源小一点呢,对于大型的游戏,系统配置是玩游戏的瓶颈所在:
最易想到的就是用for循环去创建一批怪,但是这样每次创建一个怪,都要new一次,这样明显的是不太合理的。
下面我就讲一下如何用原型模式来解决这个问题;
原型模式其实就是将一个对象再创建到另外一个可定制的对象,而且不知道任何创建的细节。
在其它语言中如果想使用原型模式,必须要在要被克隆的类中定义Clone接口,然后在具体的类中去实现这个接口。
因为我用的.NET,在.net里面,Clone方法实现用是太多了,所以.NET在System下定义了ICloneable接口,其中就是唯一的一个方法,Clone,所以在使用的过程中我们只要实现Clone接口就可以了。
下面是我模拟的代码,贴出来和大家分享下:
/// <summary> /// 怪物类 /// </summary> abstract class Monster { /// <summary> /// 怪物类构造函数 /// </summary> /// <param name="name"></param> public Monster(string name) { this.name = name; } private string name; /// <summary> /// 怪物名称 /// </summary> public string Name { get { return name; } set { name = value; } } /// <summary> /// 怪物类型 /// </summary> private string monsterType; public string MonsterType { get { return monsterType; } set { monsterType = value; } } /// <summary> /// 怪物攻击力 /// </summary> private int attack; public int Attack { get { return attack; } set { attack = value; } } private int defence; /// <summary> /// 怪物防御力 /// </summary> public int Defence { get { return defence; } set { defence = value; } } /// <summary> /// 设置怪物的熟悉值 /// </summary> public void SetProperty(string type,int attack,int defence) { this.monsterType = type; this.attack = attack; this.defence = defence; } public void SetSkill(string skillName,int defence,int attack) { skill.SkillName = skillName; skill.Defence = defence; skill.Attack = attack; } public Skill skill = new Skill(); /// <summary> /// 显示技能属性值 /// </summary> public void Display() { Console.WriteLine(string.Format("怪物名称:{0}\n怪物类型:{1};\n怪物攻击里:{2};\n怪物防御力:{3};\n怪物技能:{4};\n技能攻击力:{5};\n技能防御力:{6}\n------------------------------",this.Name,this.MonsterType,this.Attack,this.Defence,this.skill.SkillName,this.skill.Attack,this.skill.Defence)); } public abstract Monster Clone(); public Monster(Skill skill) { this.skill = (Skill)skill.Clone(); } }细心的你也许发现我没有使用.NET提供的ICloneable接口,是的,这样是方便别的语言的朋友看,所以自己就写了,下面这个技能类就是我继承微软提供的,贴出代码
/// <summary> /// 技能类 /// </summary> class Skill:ICloneable { private string skillName; /// <summary> ///技能名称 /// </summary> public string SkillName { get { return skillName; } set { skillName = value; } } private int attack; /// <summary> /// 技能攻击力 /// </summary> public int Attack { get { return attack; } set { attack = value; } } private int defence; /// <summary> /// 技能防御力 /// </summary> public int Defence { get { return defence; } set { defence = value; } } /// <summary> /// 克隆新的技能 /// </summary> /// <returns></returns> public object Clone() { return (Skill)this.MemberwiseClone(); } }具体要创建的怪类,继承怪物类的总类
class DarkTroll:Monster { /// <summary> /// 黑暗巨魔 /// </summary> /// <param name="name"></param> public DarkTroll(string name):base(name) { } /// <summary> /// 黑暗巨魔 /// </summary> /// <param name="name"></param> public DarkTroll(Skill skill0) : base(skill0) { } /// <summary> /// 克隆怪物方法 /// </summary> /// <returns></returns> public override Monster Clone() { ///创建当前对象的浅表副本,方法是创建一个新对象,然后将这个对象的非静态对象复制到新对象中,如果该字段是值类型,则对该字段进行逐一复制, ///如果是引用类型,则复制应用不复制引用对象,因此原始对象极其副本引用同一对象。 /// Monster obj = new DarkTroll(base.skill); obj.Name = this.Name; obj.MonsterType = this.MonsterType; obj.Attack = this.Attack; obj.Defence = this.Defence; return obj; } }
在这里重点提心一下:MemberwiseClone()方法如果对象中的字段是值类型,就将该字段进行逐位复制,如果是引用类型,则是复制引用而不复制值。这样的话就会出现问题,如果由于游戏的需求,同一种怪物随机出两个不同的技能中的一种,如果用Clone()方法去实现的话,那么永远都只有一种技能,这个取决于最后一次引用中存放的值。
所以在复制的过程中出现了浅复制和深复制之分,浅复制只用于值类型,深复制就比较复杂一点,需要在需要变动的类中重新实现ICloneable接口,
/// <summary> /// 克隆新的技能 /// </summary> /// <returns></returns> public object Clone() { return (Skill)this.MemberwiseClone(); }
以此来改变这一点,同时变换还有就是在引用类中必须重新改变Clone方法的写法:
/// <summary> /// 克隆怪物方法 /// </summary> /// <returns></returns> public override Monster Clone() { ///创建当前对象的浅表副本,方法是创建一个新对象,然后将这个对象的非静态对象复制到新对象中,如果该字段是值类型,则对该字段进行逐一复制, ///如果是引用类型,则复制应用不复制引用对象,因此原始对象极其副本引用同一对象。 /// Monster obj = new DarkTroll(base.skill); obj.Name = this.Name; obj.MonsterType = this.MonsterType; obj.Attack = this.Attack; obj.Defence = this.Defence; return obj; }
到此为止我们的原型模式就讲完了。
其实在我们日常编程中原型模式我们用的挺多了,比如说我们用的数据集对象DataSet,它就是一个Clone和一个Copy方法,Clone用来复制DataSet结构,但不复制DataSet数据,实现原型模式的浅复制,Copy方法不止复制了结构而且复制了数据,其实它就是原型模式的一个深复制。
Darren www.tianboo.net
- 设计模式之原型模式解决魔兽怪物创建(Darren)
- 软件开发模式之工厂模式模拟魔兽英雄创建(Darren)
- 设计模式之代理模式学习分享[Darren]
- 大话设计模式之模板方法模式(Darren)
- (创建模式)设计模式之Prototype(原型)
- 设计模式-创建型之原型模式
- Darren大话设计模式之依赖倒转原则
- JAVA设计模式创建型模式之原型模式
- 设计模式之创建类模式——原型模式
- java 设计模式-创建模式之原型模式
- 设计模式之------创建型模式(五)-----原型模式
- 设计模式 创建性模式之原型模式
- (4)设计模式之原型模式(创建型模式)
- Java设计模式之创建型模式--原型模式
- 软件设计模式之装饰模式(Darren)
- 软件设计模式之外观设计模式(Darren)
- 【设计模式】创建型模式-原型模式
- 设计模式 - 创建型模式 - 原型模式
- delphi文件后缀全解
- 字母转换
- Qt软键盘输入法
- 第十五周实验报告(任务三)【输入输出控制符】
- 随机生成10个不重复的整数
- 设计模式之原型模式解决魔兽怪物创建(Darren)
- 出生日期
- 非插件实现wordpress分页导航
- C++设计模式之九:Decorator(装饰)
- JSP中request属性大全
- 生成能动图形
- 排序
- arm linux 移植usb转串口驱动
- windows配置node环境