装饰模式
1、定义
装饰模式:动态的给一个对象增加一些额外的职责。就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案。
2、装饰模式结构
- Component(抽象构建):它是具体构建和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法。
- ConcreteComponent(具体构建):定义具体的构件对象,实现了在抽象构件中声明的方法,装饰类可以给他增加额外的职责(方法)。
- Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过子类扩展该方法,以达到装饰的目的。
- ConcreteDecorator(具体装饰类):负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用于扩展对象的行为
3、实例代码
Component 创建Person
public interface Person {
void eat();
}
ConcreteComponent 创建Man实现Person接口
public class Man implements Person {
@Override
public void eat() {
System.out.println("这个人在吃饭");
}
}
Decorator
public abstract class Decorator implements Person {
protected Person person;
public void setPerson(Person person) {
this.person = person;
}
@Override
public void eat() {
person.eat();
}
}
ConcreteDecorator
public class ManDecoratorA extends Decorator {
@Override
public void eat() {
super.eat();
reEat();
System.out.println("ManDecoratorA类");
}
public void reEat() {
System.out.println("再吃一顿饭");
}
}
public class ManDecoratorB extends Decorator {
@Override
public void eat() {
super.eat();
System.out.println("===============");
System.out.println("ManDecoratorB类");
}
}
新建测试类
public class Client {
public static void main(String[] args) {
Man man = new Man();
ManDecoratorA md1 = new ManDecoratorA();
ManDecoratorB md2 = new ManDecoratorB();
md1.setPerson(man);
md2.setPerson(md1);
md2.eat();
}
}
4、装饰模式优缺点
4.1优点
- 对于扩展一个对象的功能,装饰模式比继承更加灵活
- 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合可以创造出很多不同行为的组合,得到功能更加强大的对象
- 具体构件类和具体装饰类可以独立变化,用户根据具体需求增加新的具体构件类和具体装饰类,符合开闭原则
4.2缺点
- 使用装饰模式会产生很多小对象,占用更多的系统资源,在一定程度上影响程序的性能
- 对于多次装饰的对象,在调试时寻找错误可能需要逐级排查,较为繁琐
5、装饰模式适用环境
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤消的职责。
- 当不能采用生成子类的方法进行扩充时。