装饰器模式
装饰器模式:属于结构型设计模式,是比较简单,常见的设计模式之一。主要的目的是给现有的类加一层装饰
定义
允许向一个现有的对象添加新的功能,同时不改变它的结构,即动态地给一个类添加额外的职责。
换成大白话的说法就是,身为一个吃货的你,给你手上的那个热狗,加上香肠加上鸡蛋加上蔬菜,会让你的热狗变成真的狗吗?并不会,热狗还是那条热狗。
例子
又到了喜闻乐见的举例子时间,这次发你点福利。假如今天你的女神终于答应跟你约会了,你是不是要好好准备一下。我们来好好说道说道怎么个准备发,直接上码:
/**
* 要跟女神约会是不好打理一下自己?
* 先来个 人 的抽象类,并且会打理自己
*/
public interface Person {
public void dressUp();
}
复制代码
你要跟女神约会,总该是会打理自己的人吧。总不能邋里邋遢的出门找女神吧
/**
* 先来个 你
* 跟女神约会,总得先梳洗一番把,最基础要求,不然你女神被你臭走了怎么办?
*/
public class Man implements Person{
@Override
public void dressUp() {
System.out.println("你梳洗一番");
}
}
复制代码
好了,现在模拟一下,跟女神的约会
public class Client {
public static void main(String[] args) {
Person man = new Man();
man.dressUp();
System.out.println("去跟女神约会");
}
}
复制代码
运行结果:
但是这样真的好吗?难得女神答应你的约会,你就梳洗一番就去了?不打算给女神留下深刻印象吗?不再打扮打扮自己吗?所以,还是得再回炉重造一下。来来来,总得换上一套 帅气的衣服吧。
public class GetClothesMan implements Person{
private Person person;
public GetClothesMan(Person person) {
this.person = person;
}
@Override
public void dressUp() {
person.dressUp();
System.out.println("穿上帅气的衣服");
}
}
复制代码
再模拟一下约会情景
public class Client {
public static void main(String[] args) {
Person man = new Man();
Person getClothesMan = new GetClothesMan(man);
getClothesMan.dressUp();
System.out.println("去跟女神约会");
}
}
复制代码
运行结果:
既然都穿上了帅气的衣服了,不喷点古龙水吗?
public class GetCologne implements Person{
private Person person = null;
public GetCologne(Person person) {
this.person = person;
}
@Override
public void dressUp() {
person.dressUp();
System.out.println("喷一下古龙水");
}
}
public class Client {
public static void main(String[] args) {
Person man = new Man();
Person getClothesMan = new GetClothesMan(man);
Person getCologne = new GetCologne(getClothesMan);
getCologne.dressUp();
System.out.println("去跟女神约会");
}
}
复制代码
运行结果:
当然,你是大户人家的话,可以喷两下
public class Client {
public static void main(String[] args) {
Person getDoubleCologne = new GetCologne(new GetCologne(new GetClothesMan(new Man())));
getDoubleCologne.dressUp();
System.out.println("去跟女神约会");
}
}
复制代码
运行结果:
使用场景
- 需要扩展一个类的功能或者给一个类增加附加功能
- 需要动态地给一个对象增加功能,并且这些功能可以再动态地撤销
注意:虽然装饰器模式可以嵌套多层,但是,多层的装饰是很复杂的,所以尽量减少装饰类的数量,降低系统的复杂度。
小结
以上这种,对一个 已有的对象(梳洗一番的你) 添加 额外的功能(穿上帅气的衣服、喷上古龙水 就是经典的装饰器模式。从上面的例子中你可以看到,一直都是对要去跟女神约会的你进行妆扮(装饰)。
扩展一
装饰器模式 和 代理模式
这两种模式在写法上非常相似。但是还是有所区别的
- 角色不一样: 装饰器模式,从头到尾,角色是唯一的,都是对已有的对象进行装饰;但是 代理模式 是有2个角色的,代理人和被代理人,他们分管不同的职责。
- 目的不一样: 装饰器模式 的目的是对已有对象进行额外功能的添加(对自己投资后,还是自己);但是代理模式的目的是对已有对象的访问进行控制(也就是说,代理人决定了女神能不能约你)。
- 写法不一样: 装饰器模式 需要外部把需要装饰的对象传入,调用者需要知道是对谁进行装饰;但是代理模式,可以不需要从外部传入被代理人对象,调用者不一定需要被代理人是谁,调用者只需要跟代理者打交道。
扩展二
装饰器模式 和 继承
开发遵从的原则里 组合 > 继承 ,装饰器模式就是以组合的方式对对象进行扩展,所以它会比继承更加灵活,更好的写出健壮,可扩展性强的代码。
拿上面的喷古龙水的那一步来当例子,有时需要喷一下,有时需要喷两下。上面装饰器模式的写法,是用同一个喷古龙水的类进行了2次的包装达到了效果;那么如果用继承的写法,就需要创建2个类分别是喷一下的实现和喷两下的实现,这样就会增加类的数量,如果这样的情况多了,会让项目臃肿不好维护。