上班族大多都有睡懒觉的习惯,每天早上上班时间都很紧张,于是很多人为了多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框等,都是装饰器模式。
在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能。所有这些都可以釆用装饰器模式来实现。
当然,大家可能觉得通过继承也可以达到上面我们所说的效果,之所以不推荐使用继承的原因是因为,继承的方式不灵活,而且装饰和被装饰者的耦合度太高。
1. 装饰器模式的介绍
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
2. 装饰器模式的结构
装饰模式主要包含以下角色。
- 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
- 具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
3. 装饰器模式的实现
定义抽象构件:
package com.siyi.decoratorpattern;
//抽象构件角色
public interface Component {
public void operation();
}
定义具体构建:
package com.siyi.decoratorpattern;
//具体构件角色
public class ConcreteComponent implements Component {
public ConcreteComponent() {
System.out.println("创建具体构件角色");
}
public void operation() {
System.out.println("调用具体构件角色的方法operation()");
}
}
定义抽象装饰角色
package com.siyi.decoratorpattern;
//抽象装饰角色
public class Decorator implements Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
public void operation() {
component.operation();
}
}
定义具体装饰角色:
package com.siyi.decoratorpattern;
//具体装饰角色
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void operation() {
addedFunction();
super.operation();
}
public void addedFunction() {
System.out.println("为具体构件角色增加额外的功能addedFunction()");
}
}
Main方法:
package com.siyi.decoratorpattern;
public class Main {
public static void main(String[] args) {
Component p = new ConcreteComponent();
p.operation();
System.out.println("---------------------------------");
Component d = new ConcreteDecorator(p);
d.operation();
}
}
运行结果:
创建具体构件角色
调用具体构件角色的方法operation()
---------------------------------
为具体构件角色增加额外的功能addedFunction()
调用具体构件角色的方法operation()
4. 装饰器模式的优缺点
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
注意事项:可代替继承。