设计模式(一)

Posted on 2008-08-06 16:36 RichardHe 阅读(295) 评论(0)  编辑 收藏 引用 所属分类: 设计模式
出自http://www.cppblog.com/Fox/archive/2008/08/06/58154.html

0. Introduction

接触设计模式有两年时间了,但一直没有系统整理过,为了不至于让自己的思维被繁琐的工作一点点禁锢,还是决定总结一下,为了能够真正做到有所收获,整个系列会按照GoF的Design Patterns: Elements of Reusable Object-Oriented Software的行文思路,但不会照本宣科就是了,Wikipedia上关于23种设计模式的介绍非常全面,CSDN上也可以下载中/英文电子档,因此很多套话、类图一概省去。

最早接触设计模式的时候,难免被各种模式的联系和区别所困扰,从教科书的分析可以得到模式之间形式上的不同。但这样对于领会设计模式意义不大,因为我们掌握模式的目的是为了融会贯通,灵活运用,以对开发有所帮助。

稍微成规模的OO程序,会有大量对象,其中很多实体对象之间存在着父子、兄弟关系,对象的创建提升为一种模式。其好处在于设计模式本身所宣称的reusable,这就像堆积木盖房子一样,堆的好的情况下,换一换门窗便是另一番风景。

关于实现,我不会为了厘清模式间的区别而刻意使用相似代码实现,相反,我会根据模式本身的适用情况举例,而且大量代码基于SourceMaking

_______________________________

1. Creational Design Patterns(DP)

创建型DP抽象了类和对象的创建过程,GoF给出了5种创建型DPAbstract FactoryBuilderFactory MethodBuilderPrototypeSingleton

2. Abstract Factory

意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

1) 只提供了一个创建接口,其返回值为具体产品:如AbstractProduct *Client::CreateProduct(AbstractFactory &factory);

2) 接口的参数是一个工厂对象AbstractFactory &factory)的引用,参数类型(AbstractFactory)为抽象基类,调用时根据需要传入具体工厂对象即可;

3) 接口内部实现了一系列相关或相互依赖对象(抽象产品)的创建:当传入具体工厂时,接口实现的就是一系列具体产品的创建;

4) 创建的产品立即返回CreateProduct)。

参与者:

• AbstractFactory
— 声明一个创建抽象产品对象的操作接口。

• ConcreteFactory
— 实现创建具体产品对象的操作。

• AbstractProduct
— 为一类产品对象声明一个接口。

• ConcreteProduct
— 定义一个将被相应的具体工厂创建的产品对象。
— 实现AbstractProduct接口。

• Client
— 仅使用由AbstractFactory和AbstractProduct类声明的接口。

代码:

class AbstractFactory
{
public:
    virtual AbstractProduct *MakePartA() = 0;
    virtual AbstractProduct *MakePartB() = 0;
    virtual AbstractProduct *MakePartC() = 0;
    virtual AbstractProduct *AddPart(const AbstractProduct *pPart) = 0;
};

AbstractProduct *Client::CreateProduct(AbstractFactory &factory)
{
    AbstractProduct *pProduct = factory.CreateProduct();
    AbstractProduct *pPartA = factory.MakePartA();
    AbstractProduct *pPartB = factory.MakePartB();
    AbstractProduct *pPartC = factory.MakePartC();
    factory.AddPart(pPartA);
    factory.AddPart(pPartB);
    factory.AddPart(pPartC);
    return pProduct;
}

int main(void)
{
    Client client;           
    ConcreteFactory factory;
    client.CreateProduct(factory);
    return 0;
}

3. Builder

意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

1) director提供抽象产品创建接口:如void Director::Construct();

2) 不同产品使用同一创建过程,由director指定特定builder以生产不同产品;

3) 接口内部实现了一个复杂对象(抽象产品)的创建:当传入具体工厂时,接口实现的是一个复杂的具体产品的创建;

4) 创建的产品并不立即返回创建完毕后返回,或使用接口GetProduct)提取结果。

参与者:

• Builder
— 为创建一个Product对象的各个部件指定抽象接口。

• ConcreteBuilder
— 实现Builder的接口以构造和装配该产品的各个部件。
— 定义并明确它所创建的表示。
— 提供一个检索产品的接口。

• Director
— 构造一个使用Builder接口的对象。

• Product
— 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
— 包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

代码:

class Builder
{
public:
    virtual void MakePartA() = 0;
    virtual void MakePartB() = 0;
    virtual void MakePartC() = 0;

    Product *GetProduct()    { return _product; }

protected:
    Product *_product;
};

class Director
{
public:
    void setBuilder(Builder *b)    { _builder = b; }
    void Construct();

private:
    Builder *_builder;
};

void Director::Construct()
{
    _builder.MakePartA();
    _builder.MakePartB();
    _builder.MakePartC();
}

int main(void) {
    ConcreteBuilderA concreteBuilderA;
    ConcreteBuilderB concreteBuilderB;
    Director director;
    Product *pProduct;

    director.SetBuilder(&concreteBuilderA);
    director.Construct();
    pProduct = concreteBuilderA.GetProduct();
    pProduct->Show();

    director.SetBuilder(&concreteBuilderB);
    director.Construct();
    pProduct = concreteBuilderB.GetProduct();
    pProduct->Show();

    return 0;
}

4. Factory Method

意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。

1) 看得出该模式其实就是C++的多态特性,借继承实现。因此,其别名为虚构造器( Virtual Constructor)

2) 作为模式与C++多态特性不同的是,Creator可以定义工厂方法的缺省实现,完成缺省操作,MFC大量使用了这一思想。

参与者:

• Product
— 定义工厂方法所创建的对象的接口。

• ConcreteProduct
— 实现Product接口。

• Creator
— 声明工厂方法,该方法返回一个Product类型的对象。Creator也可以定义一个工厂方法的缺省实现,它返回一个缺省的ConcreteProduct对象。
— 可以调用工厂方法以创建一个Product对象。

• ConcreteCreator
— 重定义工厂方法以返回一个ConcreteProduct实例。

代码:

ConcreteProduct *ConcreteCreator::FactoryMethod()
{
    ConcreteProduct *pProduct = new ConcreteProduct;
    return pProduct;
}

Product *Creator::FactoryMethod()
{
    Product *pProduct = new Product;
    return pProduct;
}

int main(void) {
    Creator creator;
    ConcreteProduct *pProduct;

    pProduct = creator.FactoryMethod();
    pProduct->Show();

    return 0;
}

5. Prototype

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

1) 创建不再通过工厂新类继承(inheritance),而是通过委托(delegation)

2) 根通拷贝原型实例创建新对象。

参与者:

• ProtoType
— 声明一个克隆自身的接口。

• ConcreteProtoType
— 实现一个克隆自身的操作。

• Client
— 让一个原型克隆自身从而创建一个新的对象。

代码:

class ProtoType
{
public:
    virtual void Draw();
    virtual ProtoType *Clone() = 0;
    virtual void Initialize();
};

class ProtoTypeA: public ProtoType
{
public:
    virtual ProtoType *Clone()
    {
        return new ProtoTypeA;
    }
};

class ProtoTypeB: public ProtoType
{
public:
    virtual ProtoType *Clone()
    {
        return new ProtoTypeB;
    }
};

class Client
{
public:
    static ProtoType *Clone( int choice );

private:
    static ProtoType *s_prototypes[3];
};

ProtoType* Client::s_prototypes[] = { 0, new ProtoTypeA, new ProtoTypeB };

ProtoType *Client::Clone(int choice)
{
    return s_prototypes[choice]->Clone();
}

6. Singleton

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

1) 用静态成员函数保证上述意图。

参与者:

• Singleton
— 定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作(即C++中的一个静态成员函数)。
— 可能负责创建它自己的唯一实例。

代码:

class Singleton
{
public:
    static Singleton *GetInstance()
    {
        if (!s_instance)
            s_instance = new Singleton;
        return s_instance;
    }

    void Run()    {}

private:
    static Singleton *s_instance;
    Singleton()    {}                // Singleton cannot be created outside.
};

Singleton *GetSingleton(void)
{
    return Singleton::GetInstance();
}

int main(void)
{
    GetSingleton()->Run();

    return 0;
}

______________________________________________

代码写的都比较简单,基本可以将各种模式之间的不同体现出来了。



只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


posts - 94, comments - 138, trackbacks - 0, articles - 94

Copyright © RichardHe