单一职责模式(装饰器、桥)

在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任,即遵循“单一职责”模式(属于此模式的有Decorator和Bridge)。

装饰模式(Decorator)

装饰模式可以解决的问题:
– 使“对象功能的扩展”能够根据需要来动态地实现
– 同时避免“扩展功能的增多”带来的子类膨胀问题
– 使得任何“功能扩展变化”所导致的影响降到最低

比如说现在需要去写流的操作,需要文件流、网络流、内存流,每种流都可能需要加密或者缓存,或者兼具加密和缓存。

下述写法是错误样例,当每种流都有可能有加密或缓存的扩展操作时,不应该将具有这些扩展操作的,都单独继承为一个类。当流的类型有n种,扩展操作有m种时,若按如下写法,则最多会写出 1+n+n*m!/2种子类。这样的代码重复度十分高。

可采取下述写法:
在这种写法里,DecoratorStream类(同时也继承自Stream)应该定义一个Stream的成员变量a,接受不同的Stream类型来构造,来初始化该成员,每个DecoratorStream子类应重写Stream的虚函数,在虚函数里调用a的该函数,并附加所需内容。
采用的组合的方式,

于此,所需流的实例创建代码为:

FileStream *s1 = new FileStream();  // 基本的文件流功能
CryptoStream *s2 = new CryptoStream(s1);  // s2具有文件流加密功能
BufferedStream *s3 = new BufferedStream(s1);  // s3具有文件流缓存功能
BufferedStream *s4 = new BufferedStream(s2); // s4具有文件流加密缓存功能

桥模式(Bridge)

由于某些类型固有的实现逻辑,使得它们具有多个变化的维度。若将其多个变化维度的内容糅杂在一个基类,则会使继承复杂。

错误示范:

class Messager{
public:
    virtual void Login(string username, string password) = 0;
    virtual void SendMessage(string message) = 0;
    virtual void SendPicture(Image image) = 0;

    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;

    virtual ~Messager() {}
};

// PC平台实现
class PCMessagerBase : public Messager{
public:
    virtual void PlaySound(){
        // ...    
    }
    virtual void DrawShape(){
        // ...   
    }
    virtual void WriteText(){
        // ...   
    }
    virtual void Connect(){
        // ...
    }
};

// 业务抽象
// 1. 经典版的PC
class PCMessagerLite : public PCMessagerBase
{
public:
    virtual void Login(string username, string password){
        PCMessagerBase::Connect();
        // .....
    }
    virtual void SendMessage(string message){
        PCMessagerBase::WriteText();
        // .....
    }
    virtual void SendPicture(Image image){
        PCMessagerBase::DrawShape();
        // .....
    }
};

// 2. 华丽版的PC
class PCMessagerPefect : public PCMessagerBase
{
public:
    virtual void Login(string username, string password){
        // ..... new
        PCMessagerBase::Connect();
        // .....
    }
    virtual void SendMessage(string message){
        // ..... new
        PCMessagerBase::WriteText();
        // .....
    }
    virtual void SendPicture(Image image){
        // ..... new
        PCMessagerBase::DrawShape();
        // .....
    }
};

// Mobile平台实现
class MobileMessagerBase : public Messager{
public:
    virtual void PlaySound(){
        // ...    
    }
    virtual void DrawShape(){
        // ...   
    }
    virtual void WriteText(){
        // ...   
    }
    virtual void Connect(){
        // ...
    }
};

// 业务抽象
// 1. 经典版的Mobile
class MoblieMessagerLite : public MobileMessagerBase
{
public:
    virtual void Login(string username, string password){
        MobileMessagerBase::Connect();
        // .....
    }
    virtual void SendMessage(string message){
        MobileMessagerBase::WriteText();
        // .....
    }
    virtual void SendPicture(Image image){
        MobileMessagerBase::DrawShape();
        // .....
    }
};

// 2. 华丽版的Mobile
class MoblieMessagerPefect : public MobileMessagerBase
{
public:
    virtual void Login(string username, string password){
        // ..... new
        MobileMessagerBase::Connect();
        // .....
    }
    virtual void SendMessage(string message){
        // ..... new
        MobileMessagerBase::WriteText();
        // .....
    }
    virtual void SendPicture(Image image){
        // ..... new
        MobileMessagerBase::DrawShape();
        // .....
    }
};

正确示例:

即Bridge模式解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。Bridge有时候类似于多继承方案,但多继承往往违背单一职责原则,复用性较差,Bridge是比多继承方案更好的解决方法。

class Messager{
protected: 
    PlatformFunc *plat;
public:
    virtual void Login(string username, string password) = 0;
    virtual void SendMessage(string message) = 0;
    virtual void SendPicture(Image image) = 0;
    virtual ~Messager() {}
};

class PlatformFunc{
public:
    virtual void PlaySound() = 0;
    virtual void DrawShape() = 0;
    virtual void WriteText() = 0;
    virtual void Connect() = 0;

    virtual ~PlatformFunc() {}
};

// Platform平台实现
class PCPlatform : public PlatformFunc{
public:
    virtual void PlaySound(){
        // ...    
    }
    virtual void DrawShape(){
        // ...   
    }
    virtual void WriteText(){
        // ...   
    }
    virtual void Connect(){
        // ...
    }
};

// Mobile平台实现
class MobilePlatform : public PlatformFunc{
public:
    virtual void PlaySound(){
        // ...    
    }
    virtual void DrawShape(){
        // ...   
    }
    virtual void WriteText(){
        // ...   
    }
    virtual void Connect(){
        // ...
    }
};

class MessagerLite : public Messager{
public:
    virtual void Login(string username, string password){
        plat->Connect();
        // .....
    }
    virtual void SendMessage(string message){
        plat->WriteText();
        // .....
    }
    virtual void SendPicture(Image image){
        plat->DrawShape();
        // .....
    }
};

class MessagerPerfect : public Messager{
public:
    virtual void Login(string username, string password){
        // ..... new
        plat->Connect();
        // .....
    }
    virtual void SendMessage(string message){
        // ..... new
        plat->WriteText();
        // .....
    }
    virtual void SendPicture(Image image){
        // ..... new
        plat->DrawShape();
        // .....
    }
};

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注