首页 > 学院 > 开发设计 > 正文

七、创建型模式之建造者、原型、单例-----《大话设计模式》

2019-11-14 13:59:29
字体:
来源:转载
供稿:网友

一、建造者模式

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

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

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

   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("/n产品 创建 ----");            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;        }    }

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表