装饰模式动态的给一个对象添加一些额外的职责,来扩展对象的功能。
装饰模式很容易就联想到了人的服饰,人是原有类,服饰是装饰类,人可以灵活的穿搭服饰。也就是装饰类可以包装在人类外面也可以包装在装饰类外面,在装饰类内部增加装饰(添加新方法)。直接来看结构图(程杰 大化设计模式截图)
直接从结构图上可以看到:
Component :抽象组件角色 ,一个抽象接口,是被装饰类和装饰类的父接口。这样做的目的是 “被装饰类” 可以被 “装饰类” 包装, “装饰类” 也可以被 “装饰类” 包装,可以灵活匹配。
ConcreteComponent: 具体组件角色,为抽象组件的实现类。
Decorator: 抽象装饰角色 ,包含一个Component组件的引用,并定义了与抽象组件一致的接口。
ConcreteDecoratorA: 为抽象装饰角色的实现类。负责实现具体的装饰方法。
以下来看代码吧
1、Component接口类,有一个show方法
// Component父类
public interface Car {
public void show();
}
2、具体的实现类 ConcreteComponent,实现接口
// 跑车可以跑
public class RunCar implements Car {
public void show() {
System.out.println("可以跑");
}
}
3、抽象装饰类,添加引用关系
public abstract class CarDecorator implements Car{
// 添加引用
private Car car;
public CarDecorator(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
// 具体装饰类实现
public abstract void show();
}
4、具体装饰类实现
// 加飞行功能
public class FlyCarDecorator extends CarDecorator{
public FlyCarDecorator(Car car) {
super(car);
}
public void show() {
this.getCar().show();
this.fly();
}
// 装饰类自有方法
public void fly() {
System.out.println("添加飞行模块 ,可以飞");
}
}
// 加游泳功能
public class SwimCarDecorator extends CarDecorator {
public SwimCarDecorator(Car car) {
super(car);
}
public void show() {
this.getCar().show();
this.swim();
}
// 装饰类自有方法
public void swim() {
System.out.println("添加防水模块,可以游");
}
}
5、实现
public class MainClass {
public static void main(String[] args) {
Car car = new RunCar();
car.show();
System.out.println("---------");
Car swimcar = new SwimCarDecorator(car);
swimcar.show();
System.out.println("---------");
Car flySwimCar = new FlyCarDecorator(swimcar);
flySwimCar.show();
//可自由组合顺序
}
}
***************** 结果 ********************
跑车可以跑
---------
跑车可以跑
添加防水模块,可以游
---------
跑车可以跑
添加防水模块,可以游
添加飞行模块 ,可以飞
总结:
装饰模式为已有功能动态的添加更多功能的一种方式。把每一个额外的功能封装为装饰类中的自有方法。并且装饰类可引用被装饰的对象,重写父类的共有方法(show)。
这样可以把类的核心职责与装饰功能区分开来。在客户端有选择的,有顺序的去给对象灵活做装饰(添加功能)。但是在某些场景下,一定注意装饰的顺序,装饰多层结构,稍不留意就会产生错误。