zoukankan      html  css  js  c++  java
  • .Net设计模式_原型模式

    引言:

    原型,感觉就是拷贝,只是给拷贝分了深拷贝和浅拷贝。

    理解:

    在C#.Net里面,我们可以很容易的通过Clone()方法实现原型模式。

    任何类,只要想支持克隆,必须实现C#中的ICloneable接口。

    ICloneable接口中有一Clone方法,可以在类中复写实现自定义的克隆方法。

    克隆的实现方法有两种:浅拷贝(shallow copy)与深拷贝(deep copy)。

    说明:浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。而深拷贝是对对象实例中字段引用的对象也进行拷贝的一种方式。

    UML图:(出之http://www.cnblogs.com/zhenyulu/articles/39257.html

    示例代码:

    public interface IObjectOne
    {
        IObjectOne Clone();
        void Write();
    }
    // Object
    public class Object1 : IObjectOne
    {
        public String _val = "A";
        public User _user = new User();
    
        public IObjectOne Clone()
        {
            _user.Name = "A name";
            return (IObjectOne)this.MemberwiseClone();
        }
    
        public void Write()
        {
            Console.WriteLine(_user.Name);
            Console.WriteLine("Object " + _val);
        }
    }
    // 实体
    public class User
    {
        public String Name { get; set; }
    }

    调用

    static void Main(string[] args)
    {
        Object1 obj = new Object1();
        Object1 objCopy = (Object1)obj.Clone();
        // 值类型
        objCopy._val = "AA";
        // 引用类型
        objCopy._user.Name = "AA name";
        objCopy.Write();
    
        obj.Write();
    
        Console.ReadKey();
    }

    结果

    从结果我们看出,MemberwiseClone方法是浅拷贝,因为只有值类型的被拷贝了,引用类型的没有被拷贝。

    理解拷贝:

    public interface IObjectTwo
    {
        // 浅拷贝
        IObjectTwo Clone();
        // 深拷贝
        IObjectTwo DeepClone(String name);
        // 输出
        void Write();
    }
    
    public class Object3 : IObjectTwo
    {
        public String _val = "A";
        public User _user = new User();
    
        public Object3()
        {
            _user.Name = "A name";
        }
        // 浅拷贝
        public IObjectTwo Clone()
        {
            return (IObjectTwo)this.MemberwiseClone();
        }
        // 深拷贝
        public IObjectTwo DeepClone(String name)
        {
            Object3 nowObj = new Object3();
            User obj = new User();
            obj.Name = name;
    
            nowObj._val = this._val;
            nowObj._user = obj;
    
            return (IObjectTwo)nowObj;
        }
        // 输出
        public void Write()
        {
            Console.WriteLine(_user.Name);
            Console.WriteLine("Object " + _val);
        }
    }
    static void Main(string[] args)
    {
        Object1 obj = new Object1();
        Object1 objCopy = (Object1)obj.Clone();
        // 值类型
        objCopy._val = "AA";
        // 引用类型
        objCopy._user.Name = "AA name";
        objCopy.Write();
        obj.Write();
    
        Console.WriteLine();
        Console.WriteLine("--------------------");
        Console.WriteLine();
    
        Object3 nowObj = new Object3();
    
        Object3 objCopy2 = (Object3)nowObj.Clone();
        objCopy2._val = "XX";
        objCopy2._user.Name = "XX name";
        objCopy2.Write();
        // 深拷贝
        Object3 objCopy3 = (Object3)nowObj.DeepClone("My Name");
        objCopy3._val = "YY";
        objCopy3.Write();
        objCopy3._user.Name = "Test";
        objCopy3.Write();
    
        nowObj.Write();
    
        Console.ReadKey();
    }
    }

    结果:

    从结果知道,拷贝一个引用类型,一定是New这个对象。这个其实跟堆栈有关,当new一个对象时,会在堆上面新分配一个区域,用于新对象的存储。

    但是给一个引用对象赋值另一个引用对象时,是把引用的指针给了对象,并没有重新分配存储区域,所以修改这个对象就会影响,整个上下文中的这个对象,

    因为,修改的是一个存储区域。

    总结:(出之http://www.cnblogs.com/zhenyulu/articles/39257.html)

    1、Prototype模式允许动态增加或减少产品类。由于创建产品类实例的方法是产批类内部具有的,因此增加新产品对整个结构没有影响。
    2、Prototype模式提供了简化的创建结构。工厂方法模式常常需要有一个与产品类等级结构相同的等级结构,而Prototype模式就不需要这样。
    3、Portotype模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响老系统。
    4、产品类不需要非得有任何事先确定的等级结构,因为Prototype模式适用于任何的等级结构。

    应用场景:

    如:一个方法,里面的参数是一个实体类,ProcessMessage(User userInfo),而调用这个方法的方法是ReturnProcess()

    public void ReturnProcess(){

      User userInfo = new User();
          // 调用前

      ......

      ProcessMessage(userInfo);

      

      //调用后

      ......
    }

    那么,在ProcessMessage修改对象uerInfo,会直接影响到 调用后,userInfo的值。

    所以在一些设计中需要考虑子方法中修改对象带来的影响,

    所以我们需要深拷贝和浅拷贝。

    也就是我们说的原型模式。

    代码下载:

    百度网盘 http://pan.baidu.com/s/1c0iSVlu

    CSDN  http://download.csdn.net/detail/hater22/6847203

  • 相关阅读:
    将iso镜像转换为docker镜像
    Linux awk使用方法~~整理
    Linux sed使用方法
    Linux 环境变量梳理
    学习docker——命令总结
    Golang 字符串操作--使用strings、strconv包
    WebSocket实现一个聊天室
    学习WebSocket
    PHP面试题整理
    php使用gd库输出中文内容的图片
  • 原文地址:https://www.cnblogs.com/kimi-gyj/p/3517154.html
Copyright © 2011-2022 走看看