你的位置:首页 > ASP.net教程

[ASP.net教程]设计模式——创建型模式


解决问题:创建对象,将创建对象的任务交给另一个对象完成

组成:

  • 简单工厂:客户传递创建产品的类型到工厂类中去,工厂类根据类型实例化不同的类。
  • 工厂方法Factory Method:定义一个用户创建对象的接口,让子类决定实例化哪一个类。

                          优点:客服了简单工厂违背开放封闭原则的缺点。

  • 抽象工厂Abstract Factory:提供一个创建一系列或相关依赖对象的接口,而无需指定它们具体的类。

                          优点:让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被

                                   具体工厂的实现分离,不会出现在客户端代码中。

                          缺点:如果新增一个业务产品,就需要修改原有各工厂子类,添加生产新产品的方法,同时还需要新增每个

                                   工厂生产的具体业务产品类,才可以完全实现。

  • 建造者模式Builder:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
  • 原型模式Prototype:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
  • 单例模式Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

优点:客户不需要知道具体创建对象,隐藏了类的实例是如何被创建的。

简单工厂:

UML图:

ZY4QAYA%DN0X0RN@T{}ZJBC[8]

伪代码实现:

public class 工厂{  public static 产品 Factory(string 产品名称)  {   Product result=null;   switch(产品名称)   {     case"产品1":      result=new 产品1();      break;     case"产品2":      result=new 产品2();      break;       }   return result;  }}客户端:产品 =工厂.Factory("产品1");

工厂方法:

UML图:

image

伪代码实现:

public interface IFactory{  Product Factory();}public class FactoryProduct1 : IFactory{  public Product Factory()  {   return new Product1();  }}//客户端IFactory factory=new FactoryProduct1();Product product=factory.Factory();

抽象工厂:

 

在工厂方法(只能生产一种业务产品)的基础上扩展而来,能生产多种业务产品,如下图的用户和部门;

但是一旦我们需要增加一个新的业务产品,比如项目Project,则至少需要增加3个类,IProject、SqlserverProject、AccessProject,还需要修改IFactory、SqlserverFactory、AccessFactory,才能完全实现。

可使用简单工厂来改进抽象工厂,更进一步,通过反射+抽象工厂、反射+配置文件来进行改进。

UML图:

image

伪代码:

//客户端IFactory fac=new SqlserverFactory();//new AcessFactory();IUser iu=fac.CreatUser():iu.insert();IDepartment id=fac.CreateDepartment();id.insert();

建造者模式:

理解:指挥者指挥某某做事。比如常见举例饭店经理指挥收银员点餐、工作人员出餐就是这个思想。

UML图:

image

伪代码实现:

/// 事情public class Thing{  public void print(string Name)  {  }}// 工作者接口public interface IWorker{  void doThing();}//具体工作者1public class Worker1 : IWorker{  public void doThing()  {   // TODO: implement  }}//具体工作者2public class Worker2 : IWorker{  public void doThing()  {   // TODO: implement  }}/// 指挥者public class Director{  public Director(IWorker worker)  {   iWorker=worker;  }   public void command()  {   iworker.doThing();  }  public IWorker iWorker;}//客户端Director director=new Director(new Worker1());director.command();

 

原型模式:

     通俗的讲:就是为了复制一个对象,避免每次new类生成对象后需要重复设置相同的属性,复制后只需对个别需要个性化的属性设置个性化的值就可以了;避免每new一次,执行一次构造函数,如果构造函数的执行时间很长,多次执行导致系统低效,在初始化信息不发生变化的情况下,克隆既隐藏了对象创建的细节,又能对性能大大的提高。

重点:需要注意深复制与浅复制两种的区别。

UML图:

image

伪代码实现:

//浅复制class Program  {    static void Main(string[] args)    {      ShallowCopy sc1 = new ShallowCopy();      ShallowCopy sc2 = (ShallowCopy)sc1.Clone();      sc1.v[0] = 9;      sc1.Display();//输出:9,2,3      sc2.Display();//输出:9,2,3      Console.Read();    }  }  class ShallowCopy : ICloneable  {    public int[] v = { 1, 2, 3 };    public Object Clone()    {      return this.MemberwiseClone();//浅复制    }    public void Display()    {      foreach (int i in v)        Console.Write(i + ", ");      Console.WriteLine();    }  }

//深复制class Program  {    static void Main(string[] args)    {      DeepCopy dc1 = new DeepCopy();      DeepCopy dc2 = (DeepCopy)dc1.Clone();      dc1.v[0] = 9;      dc1.Display();      dc2.Display();      Console.Read();    }  }  class DeepCopy : ICloneable  {    public int[] v = { 1, 2, 3 };    // 默认构造函数    public DeepCopy()    {    }    // 供Clone方法调用的私有构造函数    private DeepCopy(int[] v)    {      this.v = (int[])v.Clone();    }    public Object Clone()    {      // 构造一个新的DeepCopy对象,构造参数为      // 原有对象中使用的 v       return new DeepCopy(this.v);    }    public void Display()    {      foreach (int i in v)        Console.Write(i + ", ");      Console.WriteLine();    }  }

单例模式:

使用场景:

      一个网站的服务端程序,需要考虑怎样才能承载大量用户,在做web程序的时候有各种负载均衡的方案,其基本思想就是有一个统一的入口,然后由它来分配用户到各个服务器上去。需要考虑的问题是,即使在多线程的并发状态下,用户只能通过一个唯一的入口来分配,由此引入单例模式来实现这个唯一的入口。

不要滥用Singleton模式,只有非一个实例不可的情况下才考虑引入Singleton。否则,程序的可扩展性可能会受到限制。

UML图:

image

伪代码实现,“懒汉式单例类”(被第一次引用时才会自己实例化):

class Singleton  {    private static Singleton instance;    private static readonly object syncRoot = new object();//程序运行时创建一个静态只读的进程辅助对象    private Singleton()//构造方法改成private,堵死外界通过new来创建此类实例的可能    {    }    public static Singleton GetInstance()    {      if (instance == null)//先判断实例是否存在,不存在再加锁处理,双重锁定      {        lock (syncRoot)        {          if (instance == null)          {            instance = new Singleton();          }        }      }      return instance;    }  }

C#提供了一种“静态初始化”方法,这种方法不需要开发人员显示的编写线程安全的代码,即可解决多线程环境下它是不安全的问题,称为“饿汉式单例类”(自己被加载时就实例化)。

public sealed class Singleton//sealed阻止派生发生,而派生可能会增加实例  {    private static readonly Singleton instance = new Singleton();//在第一次引用类的任何成员时创建实例,公共语言运行库负责处理变量初始化    private Singleton() { }    public static Singleton GetInstance()    {      return instance;    }  }