一颗不安分的创业心

DOTA版设计模式——原型

原型模式,说白了就是拷贝新对象,新对象是原来的对象一模一样。就像是孙悟空用毛吹出的N个孙悟空一样,他们都是一样的具有一样的状态。
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));

完整代码:
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;
        }
    }
}
posted @ 2009-07-26 23:01  pangxiaoliang[北京]流浪者  阅读(175)  评论(0编辑  收藏  举报
小豆芽之父