博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、建造者模式

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

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

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

   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;
        }
    }