zoukankan      html  css  js  c++  java
  • 七、创建型模式之建造者、原型、单例-----《大话设计模式》

    一、建造者模式

        将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

        建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。

        指挥者这个类用来控制建造过程,也用来隔离用户与建造过程的关联。

       Builder:人

       ConcreteBuilder1:胖子

       ConcreteBuilder2:瘦子

       Director:开始组装

       Product:成果

      

    image

    //具体产品类,最终形成的产品样式
     class Product
        {
           //产品的组成部分的集合
            IList<string> parts = new List<string>();
    
           //增加部件
            public void Add(string part)
            {
                parts.Add(part);
            }
            
           //列举所有的产品部件
            public void Show()
            {
                Console.WriteLine("
    产品 创建 ----");
                foreach (string part in parts)
                {
                    Console.WriteLine(part);
                }
            }
        }
    //抽象建造者类,确定有几个部件,并返回产品
    abstract class Builder
        {
            //两个部件组成
            public abstract void BuildPartA();
            public abstract void BuildPartB();
            public abstract Product GetResult();
        }
    
       //产品A实现类
        class ConcreteBuilder1 : Builder
        {
            private Product product = new Product();
            
            //将部件A组装到产品上
            public override void BuildPartA()
            {
                product.Add("部件A");
            }
    
            //将部件B组装到产品上
            public override void BuildPartB()
            {
                product.Add("部件B");
            }
    
            public override Product GetResult()
            {
                return product;
            }
        }
    
        //产品B实现类
        class ConcreteBuilder2 : Builder
        {
            private Product product = new Product();
            public override void BuildPartA()
            {
                product.Add("部件X");
            }
    
            public override void BuildPartB()
            {
                product.Add("部件Y");
            }
    
            public override Product GetResult()
            {
                return product;
            }
        }
    //指挥者类
     class Director
        {
            public void Construct(Builder builder)
            {
               //创建部件A
                builder.BuildPartA();
    
                //创建部件B
                builder.BuildPartB();
            }
        }
    //客户端代码
    static void Main(string[] args)
            {
                //初始化一个指挥者
                Director director = new Director();
                //初始化两个具体产品类
                Builder b1 = new ConcreteBuilder1();
              Builder b2 = new ConcreteBuilder2();
    
                //创建产品A
              director.Construct(b1);
                //获得最终产品
                Product p1 = b1.GetResult();
               p1.Show();
    
                //创建产品B
              director.Construct(b2);
               //获得最终产品
                Product p2 = b2.GetResult();
               p2.Show();
    
               Console.Read();
            }

    二、原型模式

        用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

        原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。

        一般在初始化的信息不发生变化的情况下,克隆是最好的办法,这样既隐藏了对象创建的细节,又对性能是大大的提高,不用重新初始化对象,而是动态地获得对象运行时的状态。

    image

    //抽象原型类
    abstract class Prototype
        {
            private string id;
    
            // 构造函数
            public Prototype(string id)
            {
                this.id = id;
            }
    
            // 属性 
            public string Id
            {
                get { return id; }
            }
           
            public abstract Prototype Clone();
        }
    
        //具体原型类1
        class ConcretePrototype1 : Prototype
        {
            public ConcretePrototype1(string id): base(id)
            {
            }
    
           //创建当前对象的浅表副本
            public override Prototype Clone()
            {
                return (Prototype)this.MemberwiseClone();
            }
        }
    
        //也可以通过实现NET提供的ICloneable接口来取代抽象类
        class ConcretePrototype2 : ICloneable
        {        
           private string id;
    
            // 构造函数
            public ConcretePrototype2 (string id)
            {
                this.id = id;
            }
            public string Id 
           { 
    get { return id; } 
           }
    
    
            public Object Clone()
            {
                return (Object)this.MemberwiseClone();
            }
        }
    //客户端代码 
    static void Main(string[] args)
            {
                //创建p1
                ConcretePrototype1 p1 = new ConcretePrototype1("I");
               //复制给c1
                ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();
                Console.WriteLine("Cloned: {0}", c1.Id);
    
                ConcretePrototype2 p2 = new ConcretePrototype2("II");
                ConcretePrototype2 c2 = (ConcretePrototype2)p2.Clone();
                Console.WriteLine("Cloned: {0}", c2.Id);
    
                // Wait for user 
                Console.Read();
    
            }

    浅表复制(MemberwiseClone()):如果字段是值类型的,则对该字段执行逐位复制;如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。

    深复制:把引用对象的变量指向复制过的新对象,而不是原有的被引用的对象。如果需要深复制,需要在复制方法中编写程序,把任何形式类型转换成值类型再复制一次。

    三、单例模式

        保证一个类仅有一个实例,并提供一个访问它的全局访问点。

        所有类都有构造方法,不编码则系统默认生成空的构造方法,若有显式定义的构造方法,默认的构造方法就会失效,将构造方法的修饰符改为private,则外部程序就不能用new来实例化它了。

        优势:让类自身复制保持它的唯一实例。这个类可以保证没有其他实例可以被创建,并且还提供了一个访问该实例的方法(对唯一的实例可以严格地控制用户怎样及何时访问它)。

    image

    //Singleton类
    class Singleton
        {
            private static Singleton instance;
            private static readonly object syncRoot = new object();
    
           //修改构造方法修饰符,使外界不能利用new创建实例
            private Singleton()
            {
            }
    
            //创建实例
            public static Singleton GetInstance()
            {
               //双重锁定,先判断实例是否存在,不存在再加锁处理
                if (instance == null)
                {
                    //不存在,则加线程锁,防止其他线程在前一个线程没有执行完的时候再次创建
                    lock (syncRoot)
                    {
    
                        if (instance == null)
                        {
                           //初始化实例
                            instance = new Singleton();
                        }
                    }
                }
                return instance;
            }
    
        }
    //客户端代码 
    static void Main(string[] args)
            {
                //用此方法初始化实例   
                Singleton s1 = Singleton.GetInstance();
                //由于s1已经创建了实例,则s2不会再次创建新实例
                Singleton s2 = Singleton.GetInstance();
    
                if (s1 == s2)
                {
                    Console.WriteLine("Objects are the same instance");
                }
    
                Console.Read();
            }

    PS:lock是确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。

    四、衍生

        静态初始化:c#与公共语言运行库提供了一种“静态初始化”方法,这种方法不需要开发人员显式地编写线程安全代码,即可解决多线程环境下它是不安全的问题。

        饿汉式单例类:静态初始化的方式是在自己被加载时就将自己实例化。一般已经足够使用

        懒汉式单例类:在第一次被引用时,才会将自己实例化。

    //增加sealed修饰符,阻止发生派生,而派生可能会增加实例
    public sealed class Singleton
        {
           //在第一次引用类的任何成员时创建实例
            private static readonly Singleton instance = new Singleton();
    
            private Singleton() { }
    
            public static Singleton GetInstance()
            {
                return instance;
            }
        }
  • 相关阅读:
    Python-文件阅读(open函数)
    列表推导式练习
    Python-集合(set)
    Python-元组(tuple)
    Python-函数-聚合和打散
    Python-列表-非count的计数方法
    Python-字典(dict)
    Python-列表(list)
    Python-字符串
    求三个元素的最大值,和最小值。
  • 原文地址:https://www.cnblogs.com/shanymen/p/4820691.html
Copyright © 2011-2022 走看看