[設計模式]結構模式-裝飾器模式(C++描述)
second60 20180429
1. 什麼是裝飾器
當我們爲一個現有類A添加新的職責時,我們可能會定義新類B繼承現有類,再添加新的操作。但是通過繼承會使問題變得越來越複雜,如果類B又有新操作時,是否又在定義個類C來繼承B呢?這樣加深了繼承的複雜度和深度,代碼也越來越難維護。
裝飾器就是爲了解決新加類職責,繼承實現的弊端,而是通過組合來實現。
2. 裝飾器結構圖
Component: 抽象構件角色,功能類和裝飾器的基類。(真實對象和裝飾對象有相同接口)
ConcreteComponent: 構件實現類。
Decorator: 裝飾類,持有一個抽象構件的引用。接受客戶端的請求。
ConcreteDecorator: 裝飾實現類,負責對構件對象新加操作。
代碼:
// 抽象構件基類
class Component
{
public:
virtual ~Component(){}
virtual void operation(){}
};
// 構件實現類
ConcreteComponent: public Component
{
public:
virtual void operation(){cout << “ConcreteComponent::operation” << endl;}
};
//裝飾器
Decorator: public Component
{
public:
Decorator(Component *component){ _component=component; }
virtual void operation(){cout << “Decorator::operation”<< endl;}
private:
Component *_component;
};
// 具體裝飾器
ConcreteDecorator: public Decorator
{
public:
ConcreteDecorator(Component* component):Decorator(component){}
void operation(){cout << “ConcreteDecorator::operation” endl;}
void new_operation(){cout << “ConcreteDecorator::new_operation” endl;}
}
3 例子
現有一類汽車,汽車可以跑,但現在需求增加,要求汽車,可以有水裏遊的功能,也有汽車可以飛行的功能。
分析:
1. 這裏的水裏遊和飛的汽車,是在原有的汽車上的裝飾,所以可以用裝飾模式來實現。
2. 水裏流和飛的汽車,有一個抽象類汽車類,可以擴展汽車的原有功能。
代碼:
// 汽車抽象類
class CarComponent
{
public:
virtual ~CarComponent(){}
virtual void move();
};
// 普通汽車
class CommonCar: public CarComponent
{
public:
void move(){cout << “CommonCar::move” << endl;}
};
// 汽車裝飾類
class DecoratorCar: public CarComponent
{
public:
DecoratorCar(CarComponent *carComponent){_carComponent = carComponent;}
virtual void move(){_carComponent->move();}
private:
CarComponent *_carComponent;
};
// 會游水的車
class SwimCar: public DecoratorCar
{
public:
SwimCar(CarComponent *carComponent): DecoratorCar(carComponent){}
void move()
{
DecoratorCar::move();
swim();
}
void swim(){cout << “swim” << endl;}
}
//會飛的車
class FlyCar: public DecoratorCar
{
public:
FlyCar(CarComponent *carComponent): DecoratorCar(carComponent){}
void move()
{
DecoratorCar::move();
fly();
}
void fly(){cout << “fly” << endl;}
}
// 使用
int main()
{
// 普通汽車
CommonCar *commonCar = new CommonCar();
commonCar->move();
// 裝飾讓汽車能遊
SwimCar *swimCar = new SwimCar(car);
swimCar->move();
//裝飾讓汽車會飛
FlyCar *flyCar = new FlyCar(car);
flyCar->move();
return 0;
}
分析:
現有的普通汽車,只需加裝飾,即可添加不同的功能,同時,如果需要添加更多的操作,只需新加裝飾子類即可。
4 優點
a) 擴展對象功能,用組合的方式實現,減少類的個數
b) 可以對一個對象多次裝飾,創造出不同行爲的組合,得到功能更強大的對象
c) 具體構建類和具體裝飾類,可以獨立變化,可根據需求增加子類
5 缺點
a) 裝飾模式複雜理解難,排查問題麻煩
6 裝飾模式和橋接模式
相同點:
a) 橋接模式是多個可變維度,通過組合,減少類的方法(類維度擴展)
b) 裝飾模式是爲現有類添加職責,通過組合,減少類的方法(類操作擴展)
7 總結
裝飾模式,降低了系統的耦合度,可以動態的增加或刪除對象的職責,並使得需要裝飾的具體構建類和具體裝飾類可以獨立變化,以便增加新的具體構建類和具體裝飾類。