装饰者模式的定义
1)装饰者模式:在不改变原有对象的情况下,动态的将新功能附加到对象,上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)
2)这里提到的动态的将新功能附加到对象和ocp原则
包含的4个角色
抽象构件角色(Component):通常是一个抽象类或者一个接口,定义了一系列方法,方法的实现可以由子类实现或者自己实现。通常不会直接使用该类,而是通过继承该类或者实现该接口来实现特定的功能。(例如,对于动物类,有一个抽象方法输出所有的功能,基本功能包括:呼吸,觅食,睡觉等等)
具体构件角色(Concrete Component):是Component的子类,实现了对应的方法,它就是那个被装饰的类。(具体构建角色可以建立很多个,例如狗,猫,鸟等等,如果是狗,我们可以装饰一些吼叫的功能,吃肉的功能;鸟可以装饰一些飞行的功能,带有翅膀的功能等等。当然这些需要在具体装饰角色中去具体定义)
装饰角色(Decorator):是Component的子类,它是具体装饰角色共同实现的抽象类(也可以是接口),并且持有一个Component类型的对象引用,它的主要作用就是把客户端的调用委派到被装饰类。
具体装饰角色(Concrete Decorator):它是具体的装饰类,是Decorator的子类,当然也是Component的子类。它主要就是定义具体的装饰功能,例如上面说的,对于鸟这个具体构建角色而言,除了具备抽象构件角色基本的功能,它还具有一些飞行的功能,带翅膀的功能。那么我们可以把这两个功能定义成一个具体装饰角色1,对于狗这个具体构件角色而言,我们可以把吼叫,吃肉这两个功能定义成一个具体装饰角色2,这样,如果我们再定义一个狼这样的具体构件角色的时候,就可以直接用具体装饰角色2来进行装饰
应用场景
假如有这么一个需求,现在有一个服务员,原来有一个功能是端盘子,现在需要给它增加一个新功能,不单单只会端盘子,还要微笑服务,
在没学习装饰者模式之前,我们可能会通过继承的方式,然后重写父类的方法,在原有基础上,写新的功能,这样做虽然能解决问题,但是耦合度太高,不利于扩展,我们知道,子类和父类之间是耦合的关系,如果有要增加很多功能,又要写很多子类
在学习了装饰者模式之后,我们可以将增强类和被增强类解耦,将功能方法抽取出来,定义成接口或者抽象类
代码:
构建抽象角色,对应服务类
public interface Component {
void function();
}
具体构建角色(对应服务员)
public class ConcreteComponent implements Component{
@Override
public void service() {
System.out.println("端盘子,上菜");
}
}
装饰角色
public class Decorator implements Component{
// 持有一个component类型的对象引用,传进来谁,我增强谁
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void service() {
// 客户端的调用委托给具体的子类
this.component.service();
}
}
具体装饰角色(增强类)
public class ConcreteDecorator extends Decorator{
public ConcreteDecorator(Component component) {
super(component);
}
@Override
public void service() {
smile();
super.service();
sweep();
}
private void sweep() {
System.out.println("打扫卫生");
}
private void smile() {
System.out.println("微笑服务");
}
}
测试类
public static void main(String[] args) {
Component component=new ConcreteComponent();
System.out.println("装饰前");
component.service();
System.out.println("装饰后");
Component newComponent=new ConcreteDecorator(component);
newComponent.service();
}