装饰模式就是动态的给一个对象添加一些额外的职责,就增加功能而言,装饰模式比生成子类更灵活。
在远古的qq聊天的时候,有一个叫qq秀的东西,很多人都在里面给自己的qq秀换装,感觉就像装饰自己一样,无论什么衣服鞋子啊什么的都可以理解为对人的装饰。
先看一下装饰模式 的结构图
图片出自大话设计模式
通过以上的结构我们可以看出,装饰模式就是通过Decorator类对Component类来包装,我们看一下Decorator类的基本实现代码:
abstract class Decorator implements Component {
private Component component;
public Decorator() {
}
public Decorator(Component component) {
this.component = component;
}
public void setComponent(Component component) {
this.component = component;
}
@Override
public void Operation() {
if (component != null) {
component.Operation();
}
}
}
其中的setComponent方法就是封装了一个component类进来。这样每个装饰对象的实现和如何使用这个对象分开了,每个装饰对象只需要关心自己的功能就好了,不需要关心这个功能是如何被添加到对象中去的。
我们接下来列举一个简单的功能,运用装饰模式来模拟一下人穿衣服,
首先我们定义一个人,因为只需要考虑核心功能所以什么都不需要添加。只知道是个人就行。其中有个show方法来展示穿的衣服。但是此时他并不知道穿什么因为衣服很多。
public class PersonMen {
private String name;
public PersonMen() {
}
public PersonMen(String name) {
this.name = name;
}
public void show() {
System.out.println(name + "今天穿了:");
}
}
然后定义一个抽象类,其中Decorate方法就是穿衣的方法与上文的setComponent方法是一样的。接下来就非常简单了,有什么衣服就定义什么类就好了只需要继承Finery类。有新衣服就拓展,旧衣服就淘汰掉。
class Finery extends PersonMen {
private PersonMen personMen;
//穿衣
public void Decorate(PersonMen personMen) {
this.personMen = personMen;
}
@Override
public void show() {
if (personMen != null) {
personMen.show();
}
}
}
接下来就非常简单了,有什么衣服就定义什么类就好了只需要继承Finery类。有新衣服就拓展,旧衣服就淘汰掉。我们随便定义两件衣服。
class TShirts extends Finery {
@Override
public void show() {
super.show();
System.out.print(" 半截袖子");
}
}
class BigTrouser extends Finery {
@Override
public void show() {
super.show();
System.out.print(" 大裤衩子");
}
}
然后我们看一下客户端代码
public class Client {
public static void main(String[] args) {
PersonMen jiangheng = new PersonMen("姜恒");
System.out.println("早上起来穿衣服");
TShirts tShirts = new TShirts();
BigTrouser bigTrouser = new BigTrouser();
tShirts.Decorate(jiangheng);
bigTrouser.Decorate(tShirts);
bigTrouser.show();
}
}
执行以下:
顺序在这里是怎么实现都行的。但是在实际的使用中还是要注意的。比如加密数据和过滤词汇都可以是数据持久化之前的装饰功能,但若先加密了数据,再用过滤功能就会出问题了。