首页 > 技术文章 > 原型模式

ningxinjie 2020-01-20 19:15 原文

适用性:

 

  1.当一个系统应该独立于它的产品创建,构成和表示时;

    2.当要实例化的类是在运行时刻指定时,例如,通过动态装载;

    3.为了避免创建一个与产品类层次平行的工厂类层次时;

    4.当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

 

说实话,我对于原型模式的理解还停留在哦Entity Mapper层面,我总是觉得它的转化也是一种原型模式,因为它也将对象拷贝到一个新的地址去了

使用原型模式代码实现如下:

 #region 抽象原型基类
    public abstract class NormalActor
    {
        public abstract NormalActor clone();
        public abstract NormalActor deepClone();

    }
    public abstract class FlyActor
    {
        public abstract FlyActor clone();

    }
    #endregion
 #region 实际需要克隆类
    public class NormalActor_Active : NormalActor
    {
        public List<string> list = new List<string>();
        int a = 0;
        public override NormalActor clone()
        {
            return (NormalActor)this.MemberwiseClone();//此为继承自object下的方法(实现浅拷贝)
        }
        public void SysWrite()
        {
            Console.WriteLine("实现啦A");
        }

        public override NormalActor deepClone()
        {
            return Program.DeepCopyByReflection(this);//实现深拷贝
        }
    }
    #region 另一个
    public class NormalActor_ActiveB : NormalActor
    {
        public List<string> list = new List<string>();
        int a = 0;
        public override NormalActor clone()
        {
            return (NormalActor)this.MemberwiseClone();//此为继承自object下的方法(实现浅拷贝)
        }
        public void SysWrite()
        {
            Console.WriteLine("实现啦B");
        }

        public override NormalActor deepClone()
        {
            return Program.DeepCopyByReflection(this);//实现深拷贝
        }
    }
    #endregion
  #region 实现类
    //按照原型模式SysClone是需要继承NormalActor抽象类,在其中将需要的方法全部抽象写出来,在SysClone中实现,我们操作的都是NormalActor
    public class SysClone
    {
        //实现浅拷贝
        public NormalActor RunNormalActorClone(NormalActor normalactor)
        {
            NormalActor normalactor1 = normalactor.clone();
            return normalactor1;
        }
        public T RunNormalActorClone<T>(NormalActor normalactor) where T : NormalActor
        {
            string className = normalactor.GetType().Name;//获取对象类名
            string thisName = typeof(T).Name;
            NormalActor normalactor1 = normalactor.clone();
            return (T)normalactor1;
        }
        //实现深拷贝
        public NormalActor RunNormalActorDeepClone(NormalActor normalactor)
        {
            NormalActor normalactor1 = normalactor.deepClone();
            return normalactor1;
        }
        public FlyActor RunFlyActorClone(FlyActor flyactor)
        {
            return flyactor.clone();
        }
    }
    #endregion
 //浅拷贝就是简单的将对象表面拷贝过来,引用类型地址拷贝来
        //深拷贝就是完全脱离原实例中引用地址,自己开辟一个新的地址
        //浅拷贝引用指向同一片内存区域,这样拷贝出来的和原始的对象的引用值发生变化,会互相影响
        //深拷贝则是讲对象中的全部提取出来,这样拷贝出来的和原始的对象的引用值发生变化,不会互相影响
        #region 利用反射实现深拷贝的方法
        public static T DeepCopyByReflection<T>(T obj)
        {
            if (obj is string || obj.GetType().IsValueType)//值类型 和string(值类型效果的引用类型) 没事
                return obj;
            //其余的都是引用类型,那么我创建一个实例,这样就指向不同的内存地址了
            object retval = Activator.CreateInstance(obj.GetType());
            FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
            foreach (var field in fields)
            {
                try
                {
                    field.SetValue(retval, DeepCopyByReflection(field.GetValue(obj)));
                }
                catch { }
            }

            return (T)retval;
        }
        #endregion

 具体调用

 SysClone sc = new SysClone();
            //克隆实例,可实现浅拷贝与深拷贝(这个与EntityHelper下的Mapper很像)
            NormalActor normalactor = sc.RunNormalActorClone(new NormalActor_ActiveB());//这里换成B那么他就是B , 这就是最开始需要掌握的思想,只有对象知道他是什么,虽然我们将对象转变为通用的接口使用,但是他是属于哪个类别的,对象始终是知道的
            NormalActor_ActiveB normalactor_active = ((NormalActor_ActiveB)normalactor);
            normalactor_active.SysWrite();

            sc.RunNormalActorClone<NormalActor_Active>(new NormalActor_Active()).SysWrite();


            FlyActor flyactor = sc.RunFlyActorClone(new FlyActor_Active());
            ((FlyActor_Active)flyactor).Fly();
            Console.ReadKey();

推荐阅读