装饰模式:
动态地给对象添加一些相关的职责。装饰模式相比与添加子类提供了一种更加灵活的方式。
UML图如下所示:
感觉上图中关键的有这几点:
- Decorator与Component的聚合关系(即Decorator中存在一个Component类型的引用),由于这个聚合关系的存在,Decorator可以通过一个Component的引用调用Component的接口
- Decorator与Component的继承关系,这个关系不是很容易理解。但是在这里联想到继承的里氏代换原则(父类出现的地方都可以替换成子类),就好理解了。即Decorator类也可以作为上面第1点中的聚合的对象,这点才是装饰模式的关键所在。
- 上图的继承关系在现实世界中不是很好理解,但是它们符合面向对象中继承需要遵守的里氏替换原则,将这个原则带入来考虑这个设计模式很多地方就可以想通了。
主要包括:
- Component(LibraryItem):定义了一个为对象动态添加功能的接口
- ConcreteComponent(Book,Video):定义了能动态添加功能的对象
- Decorator(Decorator):操作了一个Component对象的引用
- ConcreteDecorator(Borrowable,Written):往Component(以及它的子类中)中添加功能
装饰模式的代码实现:
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
class Component
{
public:
virtual void operation()=0;
};
class ConcreteComponent:public Component
{
public:
void operation()
{
std::cout<<"ConcreteCompont:operation()"<<std::endl;
}
};
class Decorator:public Component
{
public:
void operation()
{
if(component!=NULL)
{
component->operation();
}
}
void setComponent(Component * c)
{
component=c;
}
private:
Component * component;
};
class ConcreteDecoratorA:public Decorator
{
public:
void operation()
{
Decorator::operation();
std::cout<<"ConcreteDecoratorA::operation()"<<std::endl;
}
};
class ConcreteDecoratorB:public Decorator
{
public:
void operation()
{
Decorator::operation();
std::cout<<"ConcreteDecoratorB::operation()"<<std::endl;
}
};
int main()
{
std::cout<<"装饰模式测试"<<std::endl;
ConcreteComponent *c=new ConcreteComponent();
ConcreteDecoratorA *cda=new ConcreteDecoratorA();
ConcreteDecoratorB *cdb=new ConcreteDecoratorB();
cda->setComponent(c);
cdb->setComponent(cda);
std::cout<<"cda->operation() include:"<<std::endl;
cda->operation();
std::cout<<"--------------------"<<std::endl;
std::cout<<"cdb->operation() include:"<<std::endl;
cdb->operation();
delete c;
delete cda;
delete cdb;
return 0;
}
然后考虑一个具体的例子,即图书馆中的资源以及它们的一些特性,这些特性不是关键的并且可能有的时候需要有的时候又不需要,所以可以将它们不定义在各自的类中而通过装饰模式来实现。
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
/**
*一个真实的例子:模拟一个图书馆中的的资源(书,视频),它们各自的特性(可借阅,可写入)
*Component为LibraryItem
*ConcreteComponent为Book,Video
*Decorator为Decorator
*ConcreteDecorator为Borrowable,Written
*/
class LibraryItem
{
public:
virtual void show()=0;
};
class Book:public LibraryItem
{
public:
Book()
{
}
Book(string str):name(str)
{
}
void show()
{
std::cout<<"book:"<<name<<std::endl;
}
private:
string name;
};
class Video:public LibraryItem
{
public:
Video()
{
}
Video(string str):name(str)
{
}
void show()
{
std::cout<<"Video:"<<name<<std::endl;
}
private:
string name;
};
class Decorator:public LibraryItem
{
public:
Decorator()
{
}
Decorator(LibraryItem * item)
{
libraryItem=item;
}
void show()
{
if(libraryItem!=NULL)
libraryItem->show();
}
private:
LibraryItem * libraryItem;
};
class Written:public Decorator
{
public:
Written()
{
}
Written(LibraryItem* item):Decorator(item)
{
}
void show()
{
Decorator::show();
std::cout<<"written"<<std::endl;
}
};
class Borrowable:public Decorator
{
public:
Borrowable()
{
}
Borrowable(LibraryItem* item):Decorator(item)
{
}
void show()
{
Decorator::show();
std::cout<<"borrowable"<<std::endl;
}
};
int main()
{
std::cout<<"具体的装饰模式例子:"<<std::endl;
std::cout<<"-----------------------"<<std::endl;
Book *book=new Book("BigTalkDesignPattern");
Borrowable* borrowableBook=new Borrowable(book);
Written* writtenBook=new Written(borrowableBook);
writtenBook->show();
std::cout<<"-------------------------"<<std::endl;
Video* video=new Video("Walking Death");
Borrowable* borrowableVideo=new Borrowable(video);
borrowableVideo->show();
delete book;
delete borrowableBook;
delete writtenBook;
delete video;
delete borrowableVideo;
return 0;
}
执行结果如下:
时间: 2024-12-23 01:51:05