zoukankan      html  css  js  c++  java
  • 设计模式——创建型模式

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

    组成:

    • 简单工厂:客户传递创建产品的类型到工厂类中去,工厂类根据类型实例化不同的类。
    • 工厂方法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();
    }
    
    //具体工作者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图:

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

     

  • 相关阅读:
    洛谷P3292 [SCOI2016]幸运数字 线性基+倍增
    2019牛客暑期多校第五场题解ABGH
    暑假集训-8.1总结
    主席树
    2019HDU多校第四场题解
    洛谷P4570 [BJWC2011]元素 线性基
    暑假集训-7.31总结
    线性基总结
    Proj. THUIoTFuzz Paper Reading: One Engine to Fuzz 'em All: Generic Language Processor Testing with Semantic Validation
    UVALive5876-Writings on the Wall-KMP
  • 原文地址:https://www.cnblogs.com/sunjl/p/4600759.html
Copyright © 2011-2022 走看看