DOTA版设计模式——原型
原型模式,说白了就是拷贝新对象,新对象是原来的对象一模一样。就像是孙悟空用毛吹出的N个孙悟空一样,他们都是一样的具有一样的状态。
UML图:
在C#中原型模式就是要实现Clone方法,完成对对象的拷贝,framework中已经有了这个接口我们不必去重新定义了(ICloneable)。
C#中分为深拷贝和浅拷贝,浅拷贝这样实现即可:
public object Clone()
{
return this.MemberwiseClone();
}
这样代码很简单,但是有一定弊端。C#中有两种类型,引用类型和值类型。引用类型是放在托管堆中的,值类型放在堆栈中。当执行MemberwiseClone方法是返回的对象的确与原对象相同。但是两者却有很大的关联。对于值类型没有问题,而类中的引用类型成员返回的是同一对象,也就是说假如有个孙悟空类,类中包含的值类型没有问题,然而孙悟空类包含引用类型(外形类,自定义类型)。大家知道孙悟空会72般变化,那么假如我让N个孙悟空中的一个变为和尚,那么其他的孙悟空也会变为和尚,这是因为对于引用类型(外形类)MemberwiseClone传递的是引用,没有新建类。用C++语言来说就是传递给了新孙悟空对象了外形类指针,一个变化将引起多个变化。要想各个对象是互不关联的需要进行深拷贝。
测试代码:
完整代码:
UML图:
在C#中原型模式就是要实现Clone方法,完成对对象的拷贝,framework中已经有了这个接口我们不必去重新定义了(ICloneable)。
C#中分为深拷贝和浅拷贝,浅拷贝这样实现即可:
public object Clone()
{
return this.MemberwiseClone();
}
这样代码很简单,但是有一定弊端。C#中有两种类型,引用类型和值类型。引用类型是放在托管堆中的,值类型放在堆栈中。当执行MemberwiseClone方法是返回的对象的确与原对象相同。但是两者却有很大的关联。对于值类型没有问题,而类中的引用类型成员返回的是同一对象,也就是说假如有个孙悟空类,类中包含的值类型没有问题,然而孙悟空类包含引用类型(外形类,自定义类型)。大家知道孙悟空会72般变化,那么假如我让N个孙悟空中的一个变为和尚,那么其他的孙悟空也会变为和尚,这是因为对于引用类型(外形类)MemberwiseClone传递的是引用,没有新建类。用C++语言来说就是传递给了新孙悟空对象了外形类指针,一个变化将引起多个变化。要想各个对象是互不关联的需要进行深拷贝。
测试代码:
//浅拷贝
LandpyForm.Form.OutputResult("浅拷贝:MemberwiseClone");
DotaPatternLibrary.Protype.Hero hero = new DotaPatternLibrary.Protype.Terrorblade();
LandpyForm.Form.OutputResult("英雄名称:" + hero.Name);
LandpyForm.Form.OutputResult("英雄级别:" + hero.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
hero.RoleProperty.power,
hero.RoleProperty.nimble,
hero.RoleProperty.intelligence));
DotaPatternLibrary.Protype.Hero heroNew = hero.Clone() as DotaPatternLibrary.Protype.Hero;
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNew.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNew.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNew.RoleProperty.power,
heroNew.RoleProperty.nimble,
heroNew.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("升级==>");
hero.Level += 1;
hero.RoleProperty.power += 1.9m;
hero.RoleProperty.nimble += 3.2m;
hero.RoleProperty.intelligence += 1.75m;
LandpyForm.Form.OutputResult("英雄名称:" + hero.Name);
LandpyForm.Form.OutputResult("英雄级别:" + hero.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
hero.RoleProperty.power,
hero.RoleProperty.nimble,
hero.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNew.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNew.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNew.RoleProperty.power,
heroNew.RoleProperty.nimble,
heroNew.RoleProperty.intelligence));
//深拷贝
LandpyForm.Form.OutputResult("深拷贝:新对象");
DotaPatternLibrary.Protype.HeroForDeepCopy heroDeep = new DotaPatternLibrary.Protype.Syllabear();
LandpyForm.Form.OutputResult("英雄名称:" + heroDeep.Name);
LandpyForm.Form.OutputResult("英雄级别:" + heroDeep.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
heroDeep.RoleProperty.power,
heroDeep.RoleProperty.nimble,
heroDeep.RoleProperty.intelligence));
DotaPatternLibrary.Protype.HeroForDeepCopy heroNewDeep = heroDeep.Clone() as DotaPatternLibrary.Protype.HeroForDeepCopy;
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNewDeep.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNewDeep.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNewDeep.RoleProperty.power,
heroNewDeep.RoleProperty.nimble,
heroNewDeep.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("升级==>");
heroDeep.Level += 1;
heroDeep.RoleProperty.power += 1.9m;
heroDeep.RoleProperty.nimble += 3.2m;
heroDeep.RoleProperty.intelligence += 1.75m;
LandpyForm.Form.OutputResult("英雄名称:" + heroDeep.Name);
LandpyForm.Form.OutputResult("英雄级别:" + heroDeep.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
heroDeep.RoleProperty.power,
heroDeep.RoleProperty.nimble,
heroDeep.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNewDeep.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNewDeep.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNewDeep.RoleProperty.power,
heroNewDeep.RoleProperty.nimble,
heroNewDeep.RoleProperty.intelligence));
//深拷贝
LandpyForm.Form.OutputResult("深拷贝:序列化");
DotaPatternLibrary.Protype.HeroForSerializable heroSerializable = new DotaPatternLibrary.Protype.Puck();
LandpyForm.Form.OutputResult("英雄名称:" + heroSerializable.Name);
LandpyForm.Form.OutputResult("英雄级别:" + heroSerializable.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
heroSerializable.RoleProperty.power,
heroSerializable.RoleProperty.nimble,
heroSerializable.RoleProperty.intelligence));
DotaPatternLibrary.Protype.HeroForSerializable heroNewSerializable = heroSerializable.Clone() as DotaPatternLibrary.Protype.HeroForSerializable;
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNewSerializable.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNewSerializable.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNewSerializable.RoleProperty.power,
heroNewSerializable.RoleProperty.nimble,
heroNewSerializable.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("升级==>");
heroSerializable.Level += 1;
heroSerializable.RoleProperty.power += 1.9m;
heroSerializable.RoleProperty.nimble += 3.2m;
heroSerializable.RoleProperty.intelligence += 1.75m;
LandpyForm.Form.OutputResult("英雄名称:" + heroSerializable.Name);
LandpyForm.Form.OutputResult("英雄级别:" + heroSerializable.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
heroSerializable.RoleProperty.power,
heroSerializable.RoleProperty.nimble,
heroSerializable.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNewSerializable.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNewSerializable.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNewSerializable.RoleProperty.power,
heroNewSerializable.RoleProperty.nimble,
heroNewSerializable.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("浅拷贝:MemberwiseClone");
DotaPatternLibrary.Protype.Hero hero = new DotaPatternLibrary.Protype.Terrorblade();
LandpyForm.Form.OutputResult("英雄名称:" + hero.Name);
LandpyForm.Form.OutputResult("英雄级别:" + hero.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
hero.RoleProperty.power,
hero.RoleProperty.nimble,
hero.RoleProperty.intelligence));
DotaPatternLibrary.Protype.Hero heroNew = hero.Clone() as DotaPatternLibrary.Protype.Hero;
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNew.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNew.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNew.RoleProperty.power,
heroNew.RoleProperty.nimble,
heroNew.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("升级==>");
hero.Level += 1;
hero.RoleProperty.power += 1.9m;
hero.RoleProperty.nimble += 3.2m;
hero.RoleProperty.intelligence += 1.75m;
LandpyForm.Form.OutputResult("英雄名称:" + hero.Name);
LandpyForm.Form.OutputResult("英雄级别:" + hero.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
hero.RoleProperty.power,
hero.RoleProperty.nimble,
hero.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNew.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNew.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNew.RoleProperty.power,
heroNew.RoleProperty.nimble,
heroNew.RoleProperty.intelligence));
//深拷贝
LandpyForm.Form.OutputResult("深拷贝:新对象");
DotaPatternLibrary.Protype.HeroForDeepCopy heroDeep = new DotaPatternLibrary.Protype.Syllabear();
LandpyForm.Form.OutputResult("英雄名称:" + heroDeep.Name);
LandpyForm.Form.OutputResult("英雄级别:" + heroDeep.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
heroDeep.RoleProperty.power,
heroDeep.RoleProperty.nimble,
heroDeep.RoleProperty.intelligence));
DotaPatternLibrary.Protype.HeroForDeepCopy heroNewDeep = heroDeep.Clone() as DotaPatternLibrary.Protype.HeroForDeepCopy;
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNewDeep.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNewDeep.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNewDeep.RoleProperty.power,
heroNewDeep.RoleProperty.nimble,
heroNewDeep.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("升级==>");
heroDeep.Level += 1;
heroDeep.RoleProperty.power += 1.9m;
heroDeep.RoleProperty.nimble += 3.2m;
heroDeep.RoleProperty.intelligence += 1.75m;
LandpyForm.Form.OutputResult("英雄名称:" + heroDeep.Name);
LandpyForm.Form.OutputResult("英雄级别:" + heroDeep.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
heroDeep.RoleProperty.power,
heroDeep.RoleProperty.nimble,
heroDeep.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNewDeep.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNewDeep.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNewDeep.RoleProperty.power,
heroNewDeep.RoleProperty.nimble,
heroNewDeep.RoleProperty.intelligence));
//深拷贝
LandpyForm.Form.OutputResult("深拷贝:序列化");
DotaPatternLibrary.Protype.HeroForSerializable heroSerializable = new DotaPatternLibrary.Protype.Puck();
LandpyForm.Form.OutputResult("英雄名称:" + heroSerializable.Name);
LandpyForm.Form.OutputResult("英雄级别:" + heroSerializable.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
heroSerializable.RoleProperty.power,
heroSerializable.RoleProperty.nimble,
heroSerializable.RoleProperty.intelligence));
DotaPatternLibrary.Protype.HeroForSerializable heroNewSerializable = heroSerializable.Clone() as DotaPatternLibrary.Protype.HeroForSerializable;
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNewSerializable.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNewSerializable.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNewSerializable.RoleProperty.power,
heroNewSerializable.RoleProperty.nimble,
heroNewSerializable.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("升级==>");
heroSerializable.Level += 1;
heroSerializable.RoleProperty.power += 1.9m;
heroSerializable.RoleProperty.nimble += 3.2m;
heroSerializable.RoleProperty.intelligence += 1.75m;
LandpyForm.Form.OutputResult("英雄名称:" + heroSerializable.Name);
LandpyForm.Form.OutputResult("英雄级别:" + heroSerializable.Level);
LandpyForm.Form.OutputResult(String.Format("英雄属性---力量:{0},敏捷{1},智力{2}",
heroSerializable.RoleProperty.power,
heroSerializable.RoleProperty.nimble,
heroSerializable.RoleProperty.intelligence));
LandpyForm.Form.OutputResult("复制英雄名称:" + heroNewSerializable.Name);
LandpyForm.Form.OutputResult("复制英雄级别:" + heroNewSerializable.Level);
LandpyForm.Form.OutputResult(String.Format("复制英雄属性---力量:{0},敏捷{1},智力{2}",
heroNewSerializable.RoleProperty.power,
heroNewSerializable.RoleProperty.nimble,
heroNewSerializable.RoleProperty.intelligence));
完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using DotaCommon;
namespace DotaPatternLibrary.Protype
{
/// <summary>
/// 角色属性
/// </summary>
[Serializable]
public class RoleProperty
{
public decimal power;
public decimal nimble;
public decimal intelligence;
}
/// <summary>
/// 英雄
/// </summary>
public abstract class Hero : ICloneable
{
protected int _level;
protected string _name;
protected RoleProperty _roleProperty;
public string Name
{
get { return _name; }
set { _name = value; }
}
public RoleProperty RoleProperty
{
get { return _roleProperty; }
set { _roleProperty = value; }
}
public int Level
{
get { return _level; }
set { _level = value; }
}
public object Clone()
{
return this.MemberwiseClone();
}
}
/// <summary>
/// 英雄
/// </summary>
public abstract class HeroForDeepCopy : ICloneable
{
protected int _level;
protected string _name;
protected RoleProperty _roleProperty;
public string Name
{
get { return _name; }
set { _name = value; }
}
public RoleProperty RoleProperty
{
get { return _roleProperty; }
set { _roleProperty = value; }
}
public int Level
{
get { return _level; }
set { _level = value; }
}
public abstract object Clone();
}
/// <summary>
/// 英雄
/// </summary>
[Serializable]
public abstract class HeroForSerializable : ICloneable
{
protected int _level;
protected string _name;
protected RoleProperty _roleProperty;
public string Name
{
get { return _name; }
set { _name = value; }
}
public RoleProperty RoleProperty
{
get { return _roleProperty; }
set { _roleProperty = value; }
}
public int Level
{
get { return _level; }
set { _level = value; }
}
public object Clone()
{
object returnValue = null;
using (MemoryStream memoryStream = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, this);
memoryStream.Seek(0, SeekOrigin.Begin);
returnValue = formatter.Deserialize(memoryStream);
}
return returnValue;
}
}
/// <summary>
/// 灵魂守卫
/// </summary>
public class Terrorblade : Hero
{
public Terrorblade()
{
this._level = 1;
this._name = "灵魂守卫(Terrorblade)";
RoleProperty roleProperty = new RoleProperty();
roleProperty.power = 15;
roleProperty.nimble = 22;
roleProperty.intelligence = 15;
this._roleProperty = roleProperty;
}
}
/// <summary>
/// 德鲁伊
/// </summary>
public class Syllabear : HeroForDeepCopy
{
public Syllabear()
{
this._level = 1;
this._name = "德鲁伊(Syllabear)";
RoleProperty roleProperty = new RoleProperty();
roleProperty.power = 17;
roleProperty.nimble = 24;
roleProperty.intelligence = 13;
this._roleProperty = roleProperty;
}
public override object Clone()
{
Syllabear syllabear = new Syllabear();
syllabear.Name = Name;
syllabear.Level = Level;
RoleProperty roleProperty = new RoleProperty();
roleProperty.intelligence = RoleProperty.intelligence;
roleProperty.nimble = RoleProperty.nimble;
roleProperty.power = RoleProperty.power;
syllabear.RoleProperty = roleProperty;
return syllabear;
}
}
/// <summary>
/// 精灵龙
/// </summary>
[Serializable]
public class Puck : HeroForSerializable
{
public Puck()
{
this._level = 1;
this._name = "精灵龙(Puck)";
RoleProperty roleProperty = new RoleProperty();
roleProperty.power = 15;
roleProperty.nimble = 22;
roleProperty.intelligence = 25;
this._roleProperty = roleProperty;
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using DotaCommon;
namespace DotaPatternLibrary.Protype
{
/// <summary>
/// 角色属性
/// </summary>
[Serializable]
public class RoleProperty
{
public decimal power;
public decimal nimble;
public decimal intelligence;
}
/// <summary>
/// 英雄
/// </summary>
public abstract class Hero : ICloneable
{
protected int _level;
protected string _name;
protected RoleProperty _roleProperty;
public string Name
{
get { return _name; }
set { _name = value; }
}
public RoleProperty RoleProperty
{
get { return _roleProperty; }
set { _roleProperty = value; }
}
public int Level
{
get { return _level; }
set { _level = value; }
}
public object Clone()
{
return this.MemberwiseClone();
}
}
/// <summary>
/// 英雄
/// </summary>
public abstract class HeroForDeepCopy : ICloneable
{
protected int _level;
protected string _name;
protected RoleProperty _roleProperty;
public string Name
{
get { return _name; }
set { _name = value; }
}
public RoleProperty RoleProperty
{
get { return _roleProperty; }
set { _roleProperty = value; }
}
public int Level
{
get { return _level; }
set { _level = value; }
}
public abstract object Clone();
}
/// <summary>
/// 英雄
/// </summary>
[Serializable]
public abstract class HeroForSerializable : ICloneable
{
protected int _level;
protected string _name;
protected RoleProperty _roleProperty;
public string Name
{
get { return _name; }
set { _name = value; }
}
public RoleProperty RoleProperty
{
get { return _roleProperty; }
set { _roleProperty = value; }
}
public int Level
{
get { return _level; }
set { _level = value; }
}
public object Clone()
{
object returnValue = null;
using (MemoryStream memoryStream = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, this);
memoryStream.Seek(0, SeekOrigin.Begin);
returnValue = formatter.Deserialize(memoryStream);
}
return returnValue;
}
}
/// <summary>
/// 灵魂守卫
/// </summary>
public class Terrorblade : Hero
{
public Terrorblade()
{
this._level = 1;
this._name = "灵魂守卫(Terrorblade)";
RoleProperty roleProperty = new RoleProperty();
roleProperty.power = 15;
roleProperty.nimble = 22;
roleProperty.intelligence = 15;
this._roleProperty = roleProperty;
}
}
/// <summary>
/// 德鲁伊
/// </summary>
public class Syllabear : HeroForDeepCopy
{
public Syllabear()
{
this._level = 1;
this._name = "德鲁伊(Syllabear)";
RoleProperty roleProperty = new RoleProperty();
roleProperty.power = 17;
roleProperty.nimble = 24;
roleProperty.intelligence = 13;
this._roleProperty = roleProperty;
}
public override object Clone()
{
Syllabear syllabear = new Syllabear();
syllabear.Name = Name;
syllabear.Level = Level;
RoleProperty roleProperty = new RoleProperty();
roleProperty.intelligence = RoleProperty.intelligence;
roleProperty.nimble = RoleProperty.nimble;
roleProperty.power = RoleProperty.power;
syllabear.RoleProperty = roleProperty;
return syllabear;
}
}
/// <summary>
/// 精灵龙
/// </summary>
[Serializable]
public class Puck : HeroForSerializable
{
public Puck()
{
this._level = 1;
this._name = "精灵龙(Puck)";
RoleProperty roleProperty = new RoleProperty();
roleProperty.power = 15;
roleProperty.nimble = 22;
roleProperty.intelligence = 25;
this._roleProperty = roleProperty;
}
}
}