装饰器模式

模式简介

个人认为这是一个比较难理解的模式,给出一个背景实例进行说明。 假设我们有Transportation这个运输工具的抽象类,它有一个抽象的方法transform表示运输功能。现在,有三种运输工具,分别是Car、Aircraft和Ship,它们分别实现了自己的运输功能。transform仅仅是表示运输,不会完成装载和卸载货物的功能,我们需要自己实现装卸货物的功能,而整个运输流程包括运输过程和装卸过程。

假设我们有人力装卸和机械装卸两种方式。如果说不适用装饰器模式,但是我们要实现不同的运输方式和对应不同的装卸方式,最简单的思路是定义一个抽象的装卸类,假设是Load。那么,人力装卸可以继承自Load,假设是HumanLoad;同样的,机器装卸是MachineLoad类。现在,人力汽车运输可以设计为HumanCarTrans,那么它需要同时继承HumanLoadCarTrans这两个类。那么,所有的方式都对应2个类,这样会使得系统多了6个类,如果方式再多,那么结果就不可接受了。

现在,换一个方式考虑问题,装卸这个过程是抽象的。这么理解人力装卸,不论是Car、Aircraft还是Ship,都可以抽象出一个统一的过程,唯一不同的是运输的过程;同样的,机械装卸也是这么抽象。那么,不妨考虑一个这个方式,我们先定义出装卸方式的抽象基类Load;然后,派生出HumanLoadMachineLoad子类。因为运输过程是独立于装卸过程的,那么在Load基类中可以有一个抽象运输Transportation的指针,用于运行时确定不同的运输方式。而这两个具体的装卸子类首先在内部实现自己的装卸方式,然后在需要运输的时候,引入不同的运输方式即可。那么,Load及其子类就相当于装饰器了,因为它们装饰了运输环节,使得整个运输过程变得完整(这个地方说的可能不太恰当,但是基本原理是这样的)。

具体可以直接先调到下面的代码实例部分。

模式实现

给出一个一般的C++实现方法。

#include <iostream>
#include <memory>

class Component {  // 抽象组件
public:
    virtual void doOperation() = 0;
};

class ConcreteComponent : public Component {  // 有具体功能的组件
public:
    void doOperation() override {
        std::cout << "ConcreteComponent do operation\n";
    }
};

class Decorator {  // 抽象的装饰器
public:
    Decorator(std::shared_ptr<Component> component) {
        m_spComponent = std::move(component);
    }

    virtual ~Decorator() {
        m_spComponent.reset();
    }

    Decorator() = delete;

    virtual void doOperation() = 0;
protected:
    std::shared_ptr<Component> m_spComponent;
};

class ConcreteDecorator : public Decorator {  // 具体实现的装饰器
public:
    ConcreteDecorator(std::shared_ptr<Component> component):
        Decorator(std::move(component)) {}
    
    virtual ~ConcreteDecorator() {}
    
    void doOperation() override{
        std::cout << "Do some opration...\n";
        m_spComponent->doOperation();  // 调用具体组件的方法
        std::cout << "Do some other operation...\n";
    }
};

int main() {
    auto comp = std::make_shared<ConcreteComponent>();
    ConcreteDecorator cd(comp); 
    cd.doOperation();
    return 0;
}

代码实例

#include <iostream>
#include <memory>

class Transportation {
public:
    virtual void transform() = 0;
};

class Car : public Transportation {
public:
    void transform() override {
        std::cout << "Car transform\n";
    }
};

class Aircraft : public Transportation {
public:
    void transform() override {
        std::cout << "Aircraft transform\n";    
    }
};

class Ship : public Transportation {
public:
    void transform() override {
        std::cout << "Ship transform\n";
    }
};

class TransportationDecorator {
public:
    TransportationDecorator(std::shared_ptr<Transportation> trans) {
        m_spTransportation = std::move(trans);
    }

    TransportationDecorator() = delete;

    virtual ~TransportationDecorator() {
        m_spTransportation.reset();
    }

    virtual void transform() = 0;
protected:
    std::shared_ptr<Transportation> m_spTransportation;
};

class HumanTransDecorator : public TransportationDecorator {
public:
    HumanTransDecorator(std::shared_ptr<Transportation> trans):
        TransportationDecorator(std::move(trans)) {}

    HumanTransDecorator() = delete;

    virtual ~HumanTransDecorator() {}

    void transform() override {
        std::cout << "human load cargos...\n";
        m_spTransportation->transform();
        std::cout << "human unload cargos...\n";
    }
};

class MachineTransDecorator : public TransportationDecorator {
public:
    MachineTransDecorator(std::shared_ptr<Transportation> trans):
        TransportationDecorator(std::move(trans)) {}

    MachineTransDecorator() = delete;

    virtual ~MachineTransDecorator() {}

    void transform() override {
        std::cout << "machine load cargos...\n";
        m_spTransportation->transform();
        std::cout << "machine unload cargos...\n";
    }
};

int main() {
    auto car = std::make_shared<Car>();
    auto aircraft = std::make_shared<Aircraft>();
    auto ship = std::make_shared<Ship>();

    HumanTransDecorator ctd1(car), ctd2(aircraft);
    MachineTransDecorator ctd3(ship);
    ctd1.transform();
    std::cout << std::endl;
    ctd2.transform();
    std::cout << std::endl;
    ctd3.transform();
    return 0;
}

代码输出:

human load cargos...
Car transform
human unload cargos...

human load cargos...
Aircraft transform
human unload cargos...

machine load cargos...
Ship transform
machine unload cargos...
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值