目的
了解装饰器模式动机、相应的情景,所拥有的角色以主要思路。
装饰模式
动态的给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更加灵活。对象结构型模式。
动机
在不改变对象本身功能前提下给对象本身增加额外的新行为,它是一种用于替代继承的技术。引入装饰类,在装饰类中既可以调用带装饰的原有类方法,还可以增加新的方法,以扩充原有类的功能。
分类
- 透明式
- 半透明式
类图
在这里我其实有个疑问,抽象装饰者为啥要与抽象组件类成为组合关系(关联关系)后,还要继承抽象组件类。这个疑问后面慢慢解答。
- 透明式,客户端完全针对抽象编程,客户不需要知道具体的组件类与具体的装饰者类。
抽象组件
#ifndef COMPONENT_H
#define COMPONENT_H
#include <QObject>
class Component : public QObject
{
Q_OBJECT
public:
explicit Component(QObject *parent = 0);
virtual void display()=0;
signals:
public slots:
};
#endif // COMPONENT_H
#include "component.h"
Component::Component(QObject *parent)
: QObject(parent)
{
}
具体组件
#ifndef WINDOWCOMPONENT_H
#define WINDOWCOMPONENT_H
#include <QObject>
#include "component.h"
class WindowComponent : public Component
{
public:
explicit WindowComponent(Component* parent = nullptr);
protected:
virtual void display();
};
#endif // WINDOWCOMPONENT_H
#include "windowcomponent.h"
#include <iostream>
using namespace std;
WindowComponent::WindowComponent(Component *parent)
:Component(parent)
{
}
void WindowComponent::display()
{
cout << "this is window!" << endl;
}
装饰父类----也是继承于抽象组件
#ifndef COMPONENTDECORATOR_H
#define COMPONENTDECORATOR_H
#include <QObject>
#include "component.h"
class ComponentDecorator : public Component
{
public:
explicit ComponentDecorator(Component* parent = nullptr);
protected:
virtual void display();
private:
Component* m_component = nullptr;
};
#endif // COMPONENTDECORATOR_H
#include "componentdecorator.h"
ComponentDecorator::ComponentDecorator(Component* parent)
:Component(parent)
{
this->m_component = parent;
}
void ComponentDecorator::display()
{
m_component->display();
}
具体装饰者类一--------------------黑色边框
#ifndef BLACKBORDERDECORATOR_H
#define BLACKBORDERDECORATOR_H
#include <QObject>
#include "componentdecorator.h"
#include "component.h"
class BlackBorderDecorator : public ComponentDecorator
{
public:
explicit BlackBorderDecorator(Component* component = nullptr);
void setBlackBorder();
protected:
virtual void display();
};
#endif // BLACKBORDERDECORATOR_H
#include "blackborderdecorator.h"
#include <iostream>
using namespace std;
BlackBorderDecorator::BlackBorderDecorator(Component* component)
:ComponentDecorator(component)
{
}
void BlackBorderDecorator::setBlackBorder()
{
cout << "add BlackBorder for component" << endl;
}
void BlackBorderDecorator::display()
{
setBlackBorder();
ComponentDecorator::display();
}
具体装饰者类二--------------------滑动条
#ifndef SCROLLBARDECORATOR_H
#define SCROLLBARDECORATOR_H
#include <QObject>
#include "componentdecorator.h"
#include "component.h"
class ScrollBarDecorator : public ComponentDecorator
{
public:
explicit ScrollBarDecorator(Component* component = nullptr);
void setScrollBar();
protected:
virtual void display();
};
#endif // SCROLLBARDECORATOR_H
#include "scrollbardecorator.h"
#include <iostream>
using namespace std;
ScrollBarDecorator::ScrollBarDecorator(Component* component)
:ComponentDecorator(component)
{
}
void ScrollBarDecorator::setScrollBar()
{
cout << "add scrollbar for component" << endl;
}
void ScrollBarDecorator::display()
{
setScrollBar();
ComponentDecorator::display();
}
main.cpp
Component* com1, *combb, *comsb;
com1 = new WindowComponent();
combb = new BlackBorderDecorator(com1);
combb->display();
comsb = new ScrollBarDecorator(combb);
comsb->display();
return b.exec();
截图:
关于半透明模式 就不上细细说明。
总结
之所以将装饰者父类也继承于抽象组件,方便于装饰者能够之间装饰。
对于透明模式下,用户可以透明的使用装饰之前与装饰之后对象,无需要关心他们区别。要求就是,具体装饰者类中方法必须要覆盖抽象装饰者类的方法。
半透明模式下,则不一样,用户可能需要单独添加新增的业务方法,为了能调用得到的新增的方法,必须要使用具体装饰者类定义的对象。此时,客户端对于具体组件类型是透明的,对于具体装饰者类必须要指明,则是不透明的。