模式简介
个人认为这是一个比较难理解的模式,给出一个背景实例进行说明。 假设我们有Transportation
这个运输工具的抽象类,它有一个抽象的方法transform
表示运输功能。现在,有三种运输工具,分别是Car、Aircraft和Ship,它们分别实现了自己的运输功能。transform
仅仅是表示运输,不会完成装载和卸载货物的功能,我们需要自己实现装卸货物的功能,而整个运输流程包括运输过程和装卸过程。
假设我们有人力装卸和机械装卸两种方式。如果说不适用装饰器模式,但是我们要实现不同的运输方式和对应不同的装卸方式,最简单的思路是定义一个抽象的装卸类,假设是Load
。那么,人力装卸可以继承自Load
,假设是HumanLoad
;同样的,机器装卸是MachineLoad
类。现在,人力汽车运输可以设计为HumanCarTrans
,那么它需要同时继承HumanLoad
和CarTrans
这两个类。那么,所有的方式都对应2个类,这样会使得系统多了6个类,如果方式再多,那么结果就不可接受了。
现在,换一个方式考虑问题,装卸这个过程是抽象的。这么理解人力装卸,不论是Car、Aircraft还是Ship,都可以抽象出一个统一的过程,唯一不同的是运输的过程;同样的,机械装卸也是这么抽象。那么,不妨考虑一个这个方式,我们先定义出装卸方式的抽象基类Load
;然后,派生出HumanLoad
和MachineLoad
子类。因为运输过程是独立于装卸过程的,那么在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...