设计模式——创建型模式

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

 

 

组成:

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

 

 

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

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

 

 

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

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

 

 

缺点:如果新增一个业务产品,就需要修改原有各工厂子类,添加生产新产品的方法,同时还需要新增每个工厂生产的具体业务产品类,才可以完全实现。

 

 

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

 

 

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

 

 

简单工厂:

 

 

UML图:

 

 

伪代码实现:

 

 

工厂方法:

 

 

UML图:

 

 

伪代码实现:

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图:

 

 

伪代码:

//客户端

IFactory fac=new SqlserverFactory();//new AcessFactory();

 

IUser iu=fac.CreatUser():

iu.insert();

 

IDepartment id=fac.CreateDepartment();

id.insert();

 

 

建造者模式:

 

 

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

 

 

UML图:

伪代码实现:

/// 事情

public class Thing

{

   public void print(string Name)

   {

   }

}

 

 

// 工作者接口

public interface IWorker

{

   void doThing();

}

 

//具体工作者1

public class Worker1 : IWorker

{

   public void doThing()

   {

      // TODO: implement

   }

}

 

//具体工作者2

public 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图:

 

 

伪代码实现:

//浅复制

class Program

    {

        static voidMain(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 voidMain(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图:

 

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

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;

        }

    }

注意!此信息未认证,请谨慎判断信息的真实性!

全部评论
空

相关内容推荐

头像
点赞 评论 收藏
转发
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
点赞 收藏 评论
分享

全站热榜

正在热议