设计模式详解五:Factory模式


创建Factory模式(工厂模式),主要有两个目的,(1)如果一个基类有很多的子类,那么可以通过Factory模式统一创建子类对象, 这样可以达到方便维护,提高扩展性的目的; (2) 将具体化类的工作延迟到子类中,举个例子:父类A会调用到类B,进行逻辑的判断处理,但是类B是一个抽象类,类A不知道类B的具体类是什么,当创建类A的子类C就可以知道类B的子类D,这样就可以达到将不变的逻辑放在父类处理,而将具体的实现放到子类中。

一、设计模式的结构图

1、Factory类提供创建类Product的接口CreateProduct,这是工厂模式的第一个作用:负责维护众多类的创建。

2、Factory类是抽象类,Product也是抽象类,可以在抽象类中做公共的处理,而具体的实现工作延迟到子类,这就是工厂模式的第二个作用。

二、程序代码实现

首先定义和实现生产基类和子类

1、定义生产基类和它的子类

class Product;

//生产基类
class Product
{
public:
    virtual ~Product() = 0;
    
protected:
    Product();
    
private:
};

//生产子类
class SubProduct:public Product
{
public:
    ~SubProduct();
    SubProduct();
    
protected:
private:
};

2、实现生产基类和它的子类

Product::Product()
{
}

Product::~Product()
{
}

SubProduct::SubProduct()
{
    DEBUG_LOG("", "SubProduct...");
}

SubProduct::~SubProduct()
{
}

 

下面是定义和实现工厂的基类和它的子类

1、定义工厂的基类和它的子类

//工厂基类
class Factory
{
public:
    virtual ~Factory() = 0;
    virtual Product* CreateProduct() = 0;
    
protected:
    Factory();
    
private:
};

//工厂子类
class SubFactory:public Factory
{
public:
    ~SubFactory();
    SubFactory();
    
    Product* CreateProduct();
protected:
    
private:
};

2、实现工厂的基类和它的子类

Factory::Factory()
{
}

Factory::~Factory()
{
}

SubFactory::SubFactory()
{
    DEBUG_LOG("", "SubFactory...");
}

SubFactory::~SubFactory()
{
}

Product* SubFactory::CreateProduct()
{
    return new SubProduct();
}

三、测试验证结果

程序输入如下所示的代码段,然后运行调试查看结果:

Factory *fac = new SubFactory();
Product *product = fac->CreateProduct();

delete fac;
delete product;

运行结果如下所示,构造具体的工厂对象,然后工厂对象创建具体的生产对象。

[2019-05-25 14:03:49.814  SubFactory:45]   = SubFactory...
[2019-05-25 14:03:49.814  SubProduct:27]   = SubProduct...

四、总结

工厂模式可以解决两个问题,第一个是负责对象的创建,第二个是将具体类的工作延迟到子类中。上面的示例中,通过SubFactory调用CreateProduct创建具体类SubProduct,如果这时候又要创建一个新的类SubProduct2,  那么有得在SubFactory中创建方法CreateProduct2来创建具体类SubProduct2,这样类SubFactory就封闭不了,那么解决的办法就是创建Factory的一个新的子类SubFactory2。另一个方式就是CreateProduct方法提供一个参数,然后通过参数来决定创建具体的Product。

设计模式详解四:Bridge模式

Bridge模式是将两个结合的对象进行解耦,以便达到一个对象的修改不会影响到另一个对象的目的。比如,不同操作系统和不同算法的两个对象,操作系统可以调用不同的算法,而不同的算法可以运行在不同的操作系统上。这里操作系统我们认为是抽象部分,算法是实现部分。

一、设计模式的结构图

Abstraction对应操作系统部分, Imp对应算法部分。Abstraction是操作系统的基类,SubAbstraction是该基类的子类,负责实现操作系统上的公共的部分。Imp是算法的基类,SubImpA和SubImpB是该基类的子类,负责实现算法功能。Abstraction和Imp之间是一对多的关系,一个操作系统可以支持多种算法。具体形象的结构图如下图:

二、程序代码实现

首先定义实现操作系统的部分。

1、定义操作系统的基类以及它的子类

//操作系统基类
class Abstraction
{
public:
    virtual ~Abstraction();
    virtual void Operation() = 0;

protected:
    Abstraction();
    private:
};

//具体操作系统的实现
class SubAbstraction:public Abstraction {
public:
    SubAbstraction(Imp* imp);
    ~SubAbstraction();
    void Operation();

protected:
    
private:
    Imp* m_imp;
};

2、实现操作系统的基类以及它的子类

Abstraction::Abstraction()
{
}
Abstraction::~Abstraction()
{
}


SubAbstraction::SubAbstraction(Imp* imp)
{
    m_imp = imp;
}

SubAbstraction::~SubAbstraction()
{
}

void SubAbstraction::Operation()
{
    m_imp->Operation();
}

然后定义实现算法的部分

1、定义算法的基类以及它的子类

//算法的基类
class Imp
{
public:
    virtual ~Imp();
    virtual void Operation() = 0;

protected:
    Imp();
private:
};

//具体算法的实现A
class SubImpA:public Imp
{
public:
    SubImpA(); ~SubImpA();
    virtual void Operation();
    
protected:
private:
};

//具体算法的实现B
class SubImpB:public Imp
{
public:
    SubImpB(); ~SubImpB();
    virtual void Operation();
    
protected:
private:
};

2、实现算法的基类以及它的子类

Imp::Imp()
{
}

Imp::~Imp()
{
}

void Imp::Operation()
{
    DEBUG_LOG("", "call Imp");
}


SubImpA::SubImpA()
{
}

SubImpA::~SubImpA()
{
}

void SubImpA::Operation()
{
    DEBUG_LOG("", "call SubImpA");
}


SubImpB::SubImpB()
{
}

SubImpB::~SubImpB()
{
}

void SubImpB::Operation()
{
    DEBUG_LOG("", "call SubImpB");
}

三、测试验证结果

主程序中输入如下的代码段,然后编译运行查看它的运行结果

Imp *imp = new SubImpA();
Abstraction *abs = new SubAbstraction(imp);
abs->Operation();

Imp *imp2 = new SubImpB();
Abstraction *abs2 = new SubAbstraction(imp2);
abs2->Operation();

运行结果如下所示,操作系统和算法的对象通过组合的方式结合,操作系统根据不同的算法对象调用不同的算法,而操作系统内部的处理逻辑是不需要改变的。

[2019-05-19 21:16:12.453  Operation:61]   = call SubImpA
[2019-05-19 21:16:12.453  Operation:73]   = call SubImpB

四、总结

Bridge模式的原理是采用组合的方式,将两个对象结合起来,两个对象各自实现内部的处理逻辑,但是对外接口保持不变。比如上面的操作系统和算法两个对象,操作系统结合C++的多态特性,调用算法的接口,而算法接口不变,根据不同的算法内部实现不同的算法处理逻辑。当增加新的操作系统的时候,算法不需要修改。当增加新的算法的时候,操作系统也不需要修改。真正实现两个对象解耦的目的。

 

设计模式详解三:Observer模式(观察者模式)

观察者模式是一种“一(Subject)对多(Observer)”的设计模式,并且当“一”发生变化的时候,对应的“多”也能够同步收到通知或者改变。

一、设计模式的结构图

Observer模式的结构图:Subject目标基类中的Attatch函数实现将Observer指针存储到list列表,Detach函数实现将Observer指针从list列表中移除,Notify函数内部是循环检查list列表中存放的Observer指针,如果存在,那么调用Observer实现的Update函数。Observer观察者基类定义Update虚函数,它的继承者SubObserverA、SubObserverB……实现Update函数。

二、程序代码实现

1、首先定义目标基类Subject以及它的子类SubSubject

class Observer;

////目标基类
class Subject
{
public:
    virtual ~Subject();
    virtual void Attach(Observer* obv);
    virtual void Detach(Observer* obv);
    virtual void Notify();
    
protected:
    
    Subject();
private:
    list<Observer* >* m_obvs;
};

////目标实现类
class SubSubject:public Subject
{
public:
    SubSubject();
    ~SubSubject();

protected:

private:
    
};

2、实现目标基类以及它的子类SubSubject

////目标基类
Subject::Subject()
{
    m_obvs = new list<Observer*>;
}

Subject::~Subject()
{
    
}

void Subject::Attach(Observer* obv)
{
    m_obvs->push_front(obv);
}

void Subject::Detach(Observer* obv)
{
    if (obv != NULL) m_obvs->remove(obv);
}

void Subject::Notify()
{
    list<Observer*>::iterator it;
    it = m_obvs->begin();
    for (;it != m_obvs->end();it++)
    {
        (*it)->Update(this);
    }
}

////目标子类
SubSubject::SubSubject()
{
}

SubSubject::~SubSubject()
{
}

3、定义观察者基类,声明Update为虚函数,同时定义观察者的子类A和观察者的子类B,并且子类A和子类B维护者指向Subject的指针。

//// Observer观察者的基类
class Observer
{
public:
    virtual ~Observer();
    virtual void Update(Subject* sub) = 0;
    
protected:
    Observer();
private:
};

//// Observer观察者的子类A
class SubObserverA:public Observer
{
public:
    virtual Subject* GetSubject();
    SubObserverA(Subject* sub);
    virtual ~SubObserverA();
    
    //传入 Subject 作为参数,这样可以让一个 View 属于多个的 Subject。
    void Update(Subject* sub);
private:
    Subject* _sub;
};

//// Observer观察者的子类B
class SubObserverB:public Observer
{
public:
    virtual Subject* GetSubject();
    SubObserverB(Subject* sub);
    virtual ~SubObserverB();
    
    //传入 Subject 作为参数,这样可以让一个 View 属于多个的 Subject。
    void Update(Subject* sub);
    
private:
    Subject* _sub;
};

4、实现观察者基类,观察者的子类A和观察者的子类B

//// Observer观察者的基类
Observer::Observer()
{
}

Observer::~Observer()
{
}

//// Observer观察者的子类A
SubObserverA::SubObserverA(Subject* sub)
{
    _sub = sub;
    _sub->Attach(this);
}

SubObserverA::~SubObserverA()
{
    _sub->Detach(this);
    if (_sub != 0)
        delete _sub;
}

Subject* SubObserverA::GetSubject()
{
    return _sub;
}

void SubObserverA::Update(Subject* sub)
{
    DEBUG_LOG("", "SubObserverA update");
    // 由于SubObserverA持有Subject的指针,因此这里可以去调用Subject的相关方法
}

//// Observer观察者的子类B
SubObserverB::SubObserverB(Subject* sub)
{
    _sub = sub;
    _sub->Attach(this);
}

SubObserverB::~SubObserverB()
{
    _sub->Detach(this);
    if (_sub != 0)
        delete _sub;
}

Subject* SubObserverB::GetSubject()
{
    return _sub;
}

void SubObserverB::Update(Subject* sub)
{
    DEBUG_LOG("", "SubObserverB update");
    // 由于SubObserverB持有Subject的指针,因此这里可以去调用Subject的相关方法
}

三、测试验证结果

代码实现完成之后,主程序输入如下所示的代码段,用于验证subject调用Notify的时候是否会通知到注册到它的列表中的观察者对象。

SubSubject * sub = new SubSubject();
Observer *obsA = new SubObserverA(sub);
Observer *obsB = new SubObserverB(sub);

sub->Notify();

运行结果如下所示,从结果看Subject调用Notify函数之后,就会调用注册到列表中的观察者对象的Update函数。

[2019-05-12 22:40:09.426  Update:110]   = SubObserverB update
[2019-05-12 22:40:09.426  Update:85]   = SubObserverA update

由于观察者对象维护者Subject的指针,因此,可以通过观察者对象来间接调用Notify函数

SubSubject * sub = new SubSubject();
Observer *obsA = new SubObserverA(sub);
Observer *obsB = new SubObserverB(sub);

SubObserverA *obsA2 =dynamic_cast<SubObserverA *>(obsA);
obsA2->GetSubject()->Notify();

四、MVC结构的理解

MVC架构是Observer的一个实例,Observer就是观察者, Observable对应目标Subject,M代表Model,V代表View,C代表Control, Control为控制模块,接收到用户的输入信息之后,传递给Model模块,该模块进行业务处理,最后展示出不同的视图View。

五、总结

观察者模式也称为发布订阅模式,目标就是就是通知的发布者,观察者是通知的订阅者。目标可以通知观察者,并且由于观察者持有目标对象的指针,因此,观察者也可以主动触发目标去通知其他的观察者对象。