形象工程:创建型设计模式总结

图片 1

前言:早已断断续续把23种设计模式学习了一遍,可是实际运用的不是很理想。如果刻意用设计模式,你会发现一个很小的项目,很小的功能其实处处都是可以按标准模式去编码的,这个也许就是所谓的过度设计的问题;而不用设计模式,代码又写得愚蠢臃肿,除了堆砌代码实现功能之外你看不到程序更别提思想上的一丝闪光点。也许正像网上很多人说的那样,到一定境界自动就会高效运用到项目中去了。当然现在也不能放弃学习它,下面就把创建型模式再整理一遍,下次用到的时候可以对照查一查看一下,希望可以“一劳永逸”。
一、概述
1、创建型模式,就是用来创建对象的模式,抽象了实例化的过程。它帮助一个系统独立于如何创建、组合和表示它的那些对象。
2、两个主旋律:第一,将系统使用哪些具体类的信息封装起来;第二,隐藏了这些类的实例是如何被创建和组织的。外界对于这些对象只知道它们共同的接口,而不清楚其具体的实现细节。
3、作用
创建者模式作用可以概括为如下两点((1)和(2)引用网上博文):
(1)封装创建逻辑,绝不仅仅是new一个对象那么简单。
(2)封装创建逻辑变化,客户代码尽量不修改,或尽量少修改。

所属文章系列:寻找尘封的银弹:设计模式精读

//—————————15/04/07—————————-

 二、五种模式
1、单件模式(Singleton Pattern)
图片 2
单件模式(Singleton
Pattern)解决的是实体对象的个数问题,贴一段代码说明一下:

【一、从繁杂的代码中寻找简化之法】

//prototype
原型模式--对象创建型模式

图片 3图片 4Code
using System;
using System.Collections;
using System.Collections.Generic;

程序员都知道设计模式是好东西,一开始都能动力十足地去学习。但是,时间久了才发现:设计模式很难学,《设计模式》相关书籍里的细节非常复杂,学起来很吃力。即便学会了,用的地方也不多,因为项目的时间压力很大。即便有机会用,也会发现不知道何时该用哪种设计模式,这才是关键!因为这个问题一旦解决好了,项目压力再大,代码也会写得很快很漂亮,而且Bug少。

/*

//创建型设计模式总结-单例模式
namespace CreateTypePattern
{
    //饿汉式
    sealed class Singleton
    {
        //私有的唯一实例成员,在类加载的时候就创建好了单例对象
        private static readonly Singleton instance = new Singleton();

本文要讨论的“原型模式”,它的应用场景就有点模糊,《设计模式》书中举的“代码示例”,把抽象工厂模式和原型模式放在一起讲,导致我对这个模式的理解一度走偏。后来,经过不断的思考和实践,终于弄明白了。

   
1:意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

        //私有的构造方法,避免外部创建类实例
        private Singleton()
        {
        }

我们以Windows下的“画图”应用程序为例,看看它的代码的痛点到底在哪里?当我们使用原型模式之后,再看看它会给我们带来什么惊喜?

    2:动机:

        //静态方法,返回此类的唯一实例
        public static Singleton GetInstance()
        {
            return instance;
        }

先看一段未使用原型模式的代码,当然这些代码并不是Windows的源码:

    3:适用性:

    }

当用户把一个图形元素拖拽到画布上时,会调用如下函数:

       
1>当一个系统应该独立于它的产品创建、构成和表示时

    //客户端调用
    public class Program
    {
        static void Main()
        {
           Singleton instance= Singleton.GetInstance();
           Singleton instance1 = Singleton.GetInstance();

void GraphicTool::UserCreateGraphicItem(int userSelected) {

       
2>当要实例化的类是在运行时刻制定时,例如通过动态装载

           Console.WriteLine(object.ReferenceEquals(instance,instance1)); //引用指向同一个对象
           Console.WriteLine(instance.Equals(instance1)); //同一个对象

Graphic *newItem = NULL;

       
3>为了避免创建一个与产品类层次平行的工厂类层次时

           Console.ReadLine();
        }
    }

switch (userSelected)

       
4>当一个类的实例只能有几个不同状态组合中的一种时

}

case BUTTON: {

    4:结构:

2、工厂方法模式(Factory Pattern)
图片 5
在工厂方法中,工厂类成为了抽象类,其实际的创建工作将由其具体子类来完成。工厂方法的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中去,强调的是“单个对象”的变化。

newItem = new Button(p1, p2, …); // p1等参数需要从其他类中获取

        Client:

图片 6图片 7Code
using System;
using System.Collections;
using System.Collections.Generic;

break;

        prototype——————————->Prototype:

//创建型设计模式总结-工厂方法模式
namespace CreateTypePattern
{
    interface IProduct
    {

}

        Operation()                              Clone()

    }
    class ProductA : IProduct
    {

case LABEL: {

        { p = prototype->Clone()}                   |

    }
    class ProductB : IProduct
    {

newItem = new Label(p1, p2, …);

                                            |                   |

    }
    interface IFactory
    {
        IProduct CreateProduct();
    }

break;

                                ConcretePrototype1:    
ConcretePrototype2:

    class FactoryA : IFactory
    {
        public IProduct CreateProduct() { return new ProductA(); }
    }

}

                                Clone()                 Clone()

    class FactoryB : IFactory
    {
        public IProduct CreateProduct() { return new ProductB(); }
    }

                                {return copy of self}   {return copy of
self}

    //客户端调用
    public class Program
    {
        static void Main()
        {
            IFactory factory = new FactoryA();
            Console.WriteLine(factory.CreateProduct().GetType());
            Console.WriteLine(“———————————“);
            factory = new FactoryB();
            Console.WriteLine(factory.CreateProduct().GetType());
            Console.ReadLine();
        }
    }

default: {

    5:参与者:

}

return;

        1>Prototype:声明一个克隆自身的接口。

3、抽象工厂模式(Abstract Factory)

}

        2>ConcretePrototype:实现一个克隆自身的操作。

图片 8
(1).AbstractFactory:声明一个创建抽象产品对象的接口。
(2).CreateFactory:实现创建具体产品对象的操作。
(3).AbstractProduct:为一类产品对象声明接口。
(4).CreateProduct:定义一个将被相应具体工厂创建的产品对象,以实现AbstractProduct接口。
(5).仅使用AbstractFactory和AbstractProduct类声明的接口。
抽象工厂是所有工厂模式中最为抽象和最具有一般性的一种形态。抽象工厂可以向客户提供一个接口,使得客户可以在不必指定产品的具体类型的情况下,创建多个产品族中的产品对象,强调的是“系列对象”的变化。

Canvas::InsertGraphicItem;

       
3>Client:让一个原型克隆自身从而创建一个新的对象。

图片 9图片 10Code
using System;
using System.Collections;
using System.Collections.Generic;

}

   
6:协作:客户请求一个原型克隆自身。

//创建型设计模式总结-抽象工厂模式
namespace CreateTypePattern
{
    /// <summary>
    /// 抽象工厂接口,里面包含所有的产品创建的抽象方法
    /// </summary>
    abstract class AbstractFactory
    {
        public abstract AbstractProductA CreateProductA();
        public abstract AbstractProductB CreateProductB();
    }

void Canvas::InsertGraphicItem(Graphic *newItem) {

    7:效果:

    class ConcreteFactory1 : AbstractFactory
    {
        public override AbstractProductA CreateProductA()
        {
            return new ProductA1();
        }
        public override AbstractProductB CreateProductB()
        {
            return new ProductB1();
        }
    }

ItemList.Add;

        1>优点:

    class ConcreteFactory2 : AbstractFactory
    {
        public override AbstractProductA CreateProductA()
        {
            return new ProductA2();
        }
        public override AbstractProductB CreateProductB()
        {
            return new ProductB2();
        }
    }
    /// <summary>
    /// 抽象产品A 它们都有可能有两种不同的实现 ProductA1,ProductA2
    /// </summary>
    abstract class AbstractProductA
    {
    }
    /// <summary>
    /// 抽象产品B 它们都有可能有两种不同的实现 ProductB1,ProductB2
    /// </summary>
    abstract class AbstractProductB
    {
        public abstract void Interact(AbstractProductA a);
    }

           
1)运行时刻可以增加和删除产品,更加灵活。

    class ProductA1 : AbstractProductA
    {
    }

}

           
2)改变值以指定新对象。
可以为对象指定新值来实例化新的对象,

    class ProductB1 : AbstractProductB
    {
        public override void Interact(AbstractProductA a)
        {
            Console.WriteLine(this.GetType().Name +
              ” interacts with ” + a.GetType().Name);
        }
    }

这些代码看起来中规中矩,似乎没有什么可改进的余地。但是,当有一个新需求到来的时候,我们新写了一些代码以支持新功能,代码都运行正常,却总是感觉哪里不对。

             
这种设计可以极大减少系统所需的类的数目。

    class ProductA2 : AbstractProductA
    {
    }

新需求是这样的:用户可以在菜单里选择“拷贝到新图片”,也就是说,把用户正在画的图全盘拷贝到一个新图片编辑窗口里,代码可以这样写:

           
3)改变结构以制定新对象。
针对一些由部件和子部件来创建的对象,

    class ProductB2 : AbstractProductB
    {
        public override void Interact(AbstractProductA a)
        {
            Console.WriteLine(this.GetType().Name +
              ” interacts with ” + a.GetType().Name);
        }
    }

void GraphicTool::UserClickClone() {

              反映了Composite模式(改变child的多少或类型等)以及Decorator模式(暂时不知道<未知标记>)

    class Client
    {
        private AbstractProductA AbstractProductA;
        private AbstractProductB AbstractProductB;

Canvas *newCanvas = new Canvas;

              这里Clone需要实现为深拷贝,不然child都是一样的这个结构改变一下,别的结构就跟着改变了。

        // Constructor 
        public Client(AbstractFactory factory)
        {
            AbstractProductA = factory.CreateProductA();
            AbstractProductB = factory.CreateProductB();
        }

newCanvas->Brush = currentWindow->Canvas->Brush;

            4)减少子类的构造。相比较于Factory
Method,不需要创建一个creator类层次,

        public void Run()
        {
            AbstractProductB.Interact(AbstractProductA);
        }
    }
    //客户端调用
    public class Program
    {
        static void Main(string[] args)
        {
            AbstractFactory factory1 = new ConcreteFactory1();
            Client c1 = new Client(factory1);
            c1.Run();

newCanvas->Font = currentWindow->Canvas->Font;

             
需要一个对象时只用克隆一个就行,而不是靠creator类创建。

            AbstractFactory factory2 = new ConcreteFactory2();
            Client c2 = new Client(factory2);
            c2.Run();

            5)用类动态配置应用(不懂<未知标记>)

            Console.Read();
        }
    }
}

for (Graphic *item = newCanvas->ItemList.first(); item <
newCanvas->ItemList.end(); ++item) {

        2>缺陷:

4、原型模式(Prototype Pattern)

switch (item->Type

           
每一个子类都必须实现Clone操作。当类已经存在,新增Clone操作会很难。当内部包括一些不

图片 11
和工厂模式一样,同样对客户隐藏了对象创建工作,但是,与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。

case BUTTON: {

            支持拷贝(不支持拷贝,就无法调用拷贝构造函数实现Clone操作)或有循环引用(要实现深拷贝,就

图片 12图片 13Code
using System;
using System.Collections;
using System.Collections.Generic;

//需要写一些获取p1, p2等参数的代码

            要不断重复了)的对象时,实现克隆也会很困难。

//创建型设计模式总结-原型模式
namespace CreateTypePattern
{
    /// <summary>
    /// 原型类
    /// </summary>
    public abstract class Prototype
    {
    
        public Prototype(string id)
        {
            this.id = id;
        }

newItem = new Button(p1, p2, …);

    8:实现:

        private string id;
        public string Id
        {
            get { return id; }
        }

break;

       
1>使用一个原型管理器。
当一个系统中原型数目不固定时(也就是,客户会动态创建和销毁),要保持一个可

        public abstract Prototype Clone();
    }

}

         
用原型的注册表。客户可以通过注册表来存储和检索原型。

    /// <summary>
    /// 具体原型类ConcretePrototype1
    /// </summary>
    public class ConcretePrototype1 : Prototype
    {
        public ConcretePrototype1(string id)
            : base(id)
        {
        }

case LABEL: {

       
2>实现克隆操作。对一些复杂的对象进行深拷贝。

        public override Prototype Clone()
        {
            // Shallow copy 
            return (Prototype)this.MemberwiseClone();
        }
    }

newItem = new Label(p1, p2, …);

        3>初始化克隆对象
如果原型的类已经定义好了设置关键状态的操作就不用提供initialize操作,

    /// <summary>
    /// 具体原型类ConcretePrototype1
    /// </summary>
    public class ConcretePrototype2 : Prototype
    {
        // Constructor 
        public ConcretePrototype2(string id)
            : base(id)
        {
        }

break;

          否则,就必须提供一个initialize操作来初始化参数。

        public override Prototype Clone()
        {
            // Shallow copy 
            return (Prototype)this.MemberwiseClone();
        }
    }

}

    9:代码示例:      
                                                  */

    //客户端调用
    public class Program
    {
        static void Main(string[] args)
        {
            ConcretePrototype1 p1 = new ConcretePrototype1(“11111”);
            ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();
            Console.WriteLine(“Cloned id: {0}”, c1.Id);
            Console.WriteLine(p1.Equals(c1));
            Console.WriteLine(object.ReferenceEquals(p1, c1));

//原型工厂

            Console.WriteLine(p1.Id.Equals(c1.Id)); //true

default: {

class MazePrototypeFactory : public MazeFactory

            ConcretePrototype2 p2 = new ConcretePrototype2(“22222”);
            ConcretePrototype2 c2 = (ConcretePrototype2)p2.Clone();
            Console.WriteLine(“Cloned id: {0}”, c2.Id);
            Console.WriteLine(p2.Equals(c2));
            Console.WriteLine(object.ReferenceEquals(p2, c2));

return;

{

            Console.WriteLine(p2.Id.Equals(c2.Id)); //true

}

public:

            Console.Read();
        }
    }
}

item = newItem;

    MazePrototypeFactory(Maze*, Wall*, Room*, Door*);

5、建造者模式(Builder Pattern)

}

    

图片 14
(1)抽象建造者(Builder):给出一个抽象接口,以规范产品对象的各个组成部分的建造。
(2)具体建造者(Concrete
Builder):担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序的调用下创建产品的实例。
(3)导演者(Director):是与客户端打交道的角色,将创建产品的请求划分为对各个零件的建造请求,再将这些请求委派给具体建造者。
这一部分是组合到一起的算法(相对稳定)。
(4)产品(Product):建造中的对象(由多个部件组成)。
这个复杂对象的组成部分经常面临着剧烈的变化。
建造者模式把构造对象实例的逻辑移到了类的外部,在这个类的外部定义了这个类的构造逻辑。它把一个复杂对象的构造过程从对象的表示中分离出来,其直接效果是将一个复杂的对象简化为一个比较简单的目标对象。

currentWindow = new Window(); //切换到新窗口

    virtual Maze* MakeMaze() const;

图片 15图片 16Code
using System;
using System.Collections;
using System.Collections.Generic;

currentWindow->Canvas = newCanvas;

    virtual Room* MakeRoom(int) const;

//创建型设计模式总结-建造者模式
namespace CreateTypePattern
{
    /// <summary>
    /// 产品类,由多个部件组成
    /// </summary>
    class Product
    {
        IList<string> listPart = new List<string>();
        public void Add(string part) //part添加产品部件
        {
            listPart.Add(part);
        }
        public void ShowDetail()
        {
            Console.WriteLine(“Product created:”);
            foreach (string item in listPart)
            {
                Console.WriteLine(item);
            }
        }
    }

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website