装饰模式(Decorator)
简介通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰模式的目标。
模式定义
在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
通常情况下,扩展一个类的功能会使用继承方式来实现。但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。如果使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰模式的目标。
优缺点
优点
- 采用装饰模式扩展对象的功能比采用继承方式更加灵活
- 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合
缺点
- 装饰模式增加了许多子类,如果过度使用会使程序变得很复杂
适用场景
- 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时
- 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现
- 当对象的功能要求可以动态地添加,也可以再动态地撤销时
模型结构
- 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象;
- 具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责;
- 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能;
- 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任;
模型实现
package com.company.decorator;
public class DecoratorPattern {
public static void main(String[] args) {
Component zs = new Person("张三");
System.out.println("===================只装饰衣服===================");
Decorator clothesDecorator = new ClothesDecorator(zs);
clothesDecorator.show();
System.out.println("===================装饰衣服的基础上再装饰裤子===================");
Decorator trousersDecorator = new TrousersDecorator(clothesDecorator);
trousersDecorator.show();
}
}
//构件接口
interface Component {
void show();//构件方法
}
//具体构件角色==>人
class Person implements Component {
private final String name;
public Person(String name) {
this.name = name;
}
@Override
public void show() {
System.out.println(this.name + " 的装饰");
}
}
//抽象装饰器
abstract class Decorator implements Component {
private final Component component;
//装饰器构造方法,传入构件角色
public Decorator(Component component) {
this.component = component;
}
public void show() {
if (this.component != null) {
this.component.show();
}
}
}
//具体装饰器===》衣服
class ClothesDecorator extends Decorator {
public ClothesDecorator(Component component) {
super(component);
}
public void show() {
super.show();
System.out.println("装饰===》衣服");
}
}
//具体装饰器===》裤子
class TrousersDecorator extends Decorator {
public TrousersDecorator(Component component) {
super(component);
}
public void show() {
super.show();
System.out.println("装饰===》裤子");
}
}
运行结果:
===================只装饰衣服===================
张三 的装饰
装饰===》衣服
===================装饰衣服的基础上再装饰裤子===================
张三 的装饰
装饰===》衣服
装饰===》裤子