设计模式

1.设计模式----访问者模式

 

访问者模式(Visitor Pattern)是GoF提出的23种设计模式中的一种,属于行为模式。据《大话设计模式》中说算是最复杂也是最难以理解的一种模式了。
定义(源于GoF《Design Pattern》):表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。
从定义可以看出结构对象是使用访问者模式必备条件,而且这个结构对象必须存在遍历自身各个对象的方法。这便类似于Java语言当中的collection概念了。
设计模式_第1张图片
涉及角色 :
1.Visitor 抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具休访问者的具休元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
2.ConcreteVisitor.具体访问者角色,实现Visitor声明的接口。
3.Element 定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。
4.ConcreteElement 具体元素,实现了抽象元素(Element)所定义的接受操作接口。
5.ObjectStructure 结构对象角色,这是使用访问者模式必备的角色。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。
访问者模式的几个特点:
访问者模式把 数据结构和作用于结构上的操作解耦合,使得操作集合可相对自由地演化。
访问者模式适用于 数据结构相对稳定算法又易变化的系统。因为访问者模式使得算法操作增加变得容易。若系统 数据结构对象易于变化,经常有新的 数据对象增加进来,则不适合使用访问者模式。
访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。访问者模式将有关行为集中到一个访问者对象中,其改变不影响系统 数据结构。其缺点就是增加新的 数据结构很困难。
适用情况 :
1) 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
2)  需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor模式使得你可以将相关的操作集中起来 定义在一个类中。
3) 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
4)  定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
C++实现:
复制代码
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>

using namespace std;

class Element;
//抽象访问者类
class Visitor
{
public:
    virtual void Visit(Element *element) = 0;
};
//抽象Element类
class Element
{
protected:
    string m_name;
public:
    Element(string name) : m_name(name) {}
    virtual void Accept(Visitor *visitor)
    {
        visitor->Visit(this);
    }
    string &GetName()
    {
        return m_name;
    }
};
//具体Element类
class ConcreteElementA : public Element
{
public:
    ConcreteElementA(string name) : Element(name) {}
};

class ConcreteElementB : public Element
{
public:
    ConcreteElementB(string name) : Element(name) {}
};

//具体的访问者类
class ConcreteVisitorA : public Visitor
{
public:
    void Visit(Element *element)
    {
        cout << element->GetName() << " execute behavior A" << endl;
    }
};

class ConcreteVisitorB : public Visitor
{
public:
    void Visit(Element *element)
    {
        cout << element->GetName() << " execute behavior B" << endl;
    }
};
复制代码

客户端调用代码:

复制代码
#include "stdafx.h"
#include "Visitor.h"

int _tmain(int argc, _TCHAR* argv[])
{
    Element *element1 = new ConcreteElementA("元素A");
    Element *element2 = new ConcreteElementB("元素B");
    Visitor *visitor1 = new ConcreteVisitorA();
    Visitor *visitor2 = new ConcreteVisitorB();
    element1->Accept(visitor1);
    element1->Accept(visitor2);
    element2->Accept(visitor1);
    element2->Accept(visitor2);

    delete visitor1, visitor2;
    delete element1, element2;

    getchar();
    return 0;
}
复制代码

正如上面所说,若数据结构易变,则不适合使用访问者模式,本例中如果Element类的GetName方法参数或名称改变,则所有访问者类均需要变化。

2. 设计模式----建造者模式

定义

将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。

实用范围

1    当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2    当构造过程必须允许被构造的对象有不同表示时。

角色

在这样的设计模式中,有以下几个角色:
1    builder:为创建一个产品对象的各个部件指定抽象接口。
2    ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并 提供一个检索产品的接口。
3    Director:构造一个使用Builder接口的对象。
4    Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
C++实现:
复制代码
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

using namespace std;
//抽象建造者
class Builder
{
public:
    virtual void BuildHead() = 0;
    virtual void BuildBody() = 0;
    virtual void BuildFoot() = 0;
};
//具体的建造者类
class ManBuilder : public Builder
{
public:
    void BuildHead() { cout << "build man head" << endl; };
    void BuildBody() { cout << "build man body" << endl; };
    void BuildFoot() { cout << "build man foot" << endl; };
};

class WomanBuilder : public Builder
{
public:
    void BuildHead() { cout << "build woman head" << endl; };
    void BuildBody() { cout << "build woman body" << endl; };
    void BuildFoot() { cout << "build woman foot" << endl; };
};

//构造的指挥官
class Director
{
public:
    void Create(Builder *pBuilder)
    {
        pBuilder->BuildHead();
        pBuilder->BuildBody();
        pBuilder->BuildFoot();
    }
};
复制代码

客户端调用代码:

复制代码
#include "stdafx.h"
#include "Builder.h"

int _tmain(int argc, _TCHAR* argv[])
{
    Builder *builder1 = new ManBuilder();
    Builder *builder2 = new WomanBuilder();
    Director *director = new Director();
    director->Create(builder1);
    director->Create(builder2);

    delete director;
    delete builder1, builder2;

    getchar();
    return 0;
}
复制代码

 

这里指挥官可以build不同的对象了。

3. 设计模式----抽象工厂模式

抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。根据LSP原则,任何接受父类型的地方,都应当能够接受子类型。因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例,而不是这些抽象产品的实例。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。

定义

为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类

简介

当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产
设计模式_第2张图片

  抽象工厂模式类图

产品角色都有两个具体产品。抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
每一个模式都是针对一定问题的解决方案, 工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结构。

产品族

是指位于不同产品等级结构中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。显然,每一个产品族中含有产品的数目,与产品等级结构的数目是相等的,形成一个二维的坐标系,水平坐标是产品等级结构,纵坐标是产品族。叫做相图。
当有多个不同的等级结构的产品时,如果使用工厂方法模式就势必要使用多个独立的工厂等级结构来对付这三个产品的等级结构。如果这些产品等级结构是平行的,会导致多个平行的工厂等级结构。
抽象工厂模式使用同一个 工厂等级结构负责三个不同产品等级结构产品对象的创建。
对于每一个产品族,都有一个具体工厂。而每一个具体工厂创建属于同一个产品族,但是分属于不同等级结构的产品。
通过引进抽象工厂模式,可以处理具有相同(或者相似)等级结构的多个产品族中的产品对象的创建问题。
由于每个具体工厂角色都需要负责两个不同等级结构的产品对象的创建,因此每个工厂角色都需要提供两个工厂方法,分别用于创建两个等级结构的产品。既然每个具体工厂角色都需要实现这两个工厂方法,所以具有一般性,不妨抽象出来,移动到抽象工厂角色中加以声明。

使用情况

1.系统不依赖于产品类实例如何被创建,组合和表达的细节。
2.系统的产品有多于一个的产品族,而系统只消费其中某一族的产品(抽象工厂模式的原始用意Unix&Windows)
Button--->UnixButton/WinButton
Text----->UnixText/WinText
Unix产品族和Windows产品族,不会同时使用。
Factory--->UnixFactory/WinFactory
3.同属于同一个产品族是在一起使用的。这一约束必须在系统的设计中体现出来。
4.系统提供一个产品类的库,所有产品以同样的接口出现,从而使 客户端不依赖于实现。
C++实现:
复制代码
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

using namespace std;

//CPU
class CPU
{
public:
    virtual void show() = 0;
};

class macCPU : public CPU
{
public:
    void show()
    {
        cout << "show mac cpu" << endl;
    }
};

class pcCPU : public CPU
{
public:
    void show()
    {
        cout << "show pc cpu" << endl;
    }
};
//内存
class Ram
{
public:
    virtual void show() = 0;
};

class macRam : public Ram
{
public:
    void show()
    {
        cout << "show mac ram" << endl;
    }
};

class pcRam : public Ram
{
public:
    void show()
    {
        cout << "show pc ram" << endl;
    }
};
//抽象工厂
class AbstractFactory
{
public:
    virtual CPU *CreateCPU() = 0;
    virtual Ram *CreateRam() = 0;
};
//具体的工厂
//mac工厂
class MacFactory : public AbstractFactory
{
public:
    CPU *CreateCPU()
    {
        return new macCPU();
    }
    Ram *CreateRam()
    {
        return new macRam();
    }
};
//pc工厂
class PCFactory : public AbstractFactory
{
public:
    CPU *CreateCPU()
    {
        return new pcCPU();
    }
    Ram *CreateRam()
    {
        return new pcRam();
    }
};
复制代码

客户端调用代码:

复制代码
#include "stdafx.h"
#include "AbstractFactory.h"

int _tmain(int argc, _TCHAR* argv[])
{
    AbstractFactory *macFactory = new MacFactory();
    AbstractFactory *pcFactory = new PCFactory();

    CPU *cpu1 = macFactory->CreateCPU();
    Ram *ram1 = macFactory->CreateRam();
    cpu1->show();
    ram1->show();

    CPU *cpu2 = pcFactory->CreateCPU();
    Ram *ram2 = pcFactory->CreateRam();
    cpu2->show();
    ram2->show();

    delete cpu1, ram2, cpu2, ram2;
    delete macFactory, pcFactory;

    getchar();
    return 0;
}
复制代码

使用抽象工厂,可以派生出许多不同的产品族,每增加一个产品族,只需要派生出一个子工厂类即可。

 

4. 设计模式----简单工厂模式

从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种 GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
实现方式(附图)
设计模式_第3张图片
简单工厂模式的UML类图(见上图)
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
该模式中包含的角色及其职责
工厂(Creator)角色
简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
抽象产品(Product)角色
简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色
是简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

优缺点

优点
工厂类是整个模式的关键.包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象.通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的.明确了各自的职责和权利,有利于整个 软件体系结构的优化。
缺点
由于工厂类集中了所有实例的创建逻辑,违反了 高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
这些缺点在 工厂方法模式中得到了一定的克服。
使用场景
工厂类负责创建的对象比较少;
客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用。
C++实现
复制代码
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

using namespace std;

//简单工厂模式
enum PDTYPE {PRODUCTA, PRODUCTB};
//产品抽象类
class Product
{
public:
    virtual void show() = 0;
};
//产品A
class ProductA : public Product
{
    void show()
    {
        cout << "show product A" << endl;
    }
};
//产品B
class ProductB : public Product
{
    void show()
    {
        cout << "show product B" << endl;
    }
};
//简单工厂类
class SimpleFactory
{
public:
    static Product *CreateProductFactory(PDTYPE ptype)
    {
        switch(ptype) {
            case PRODUCTA:
                return new ProductA();    //生成产品A
            case PRODUCTB:
                return new ProductB();    //生成产品B
            default:
                return NULL;
        }

    }
};
复制代码

客户端调用代码:

复制代码
int _tmain(int argc, _TCHAR* argv[])
{
    Product *product1 = SimpleFactory::CreateProductFactory(PRODUCTA);
    Product *product2 = SimpleFactory::CreateProductFactory(PRODUCTB);
    product1->show();
    product2->show();

    delete product1, product2;

    getchar();
    return 0;
}
复制代码

该模式如其名“简单”

你可能感兴趣的:(设计模式)