装饰设计模式:
动态地给对象添加一些额外的职责。就增加功能来说,它相比生成子类更加灵活。
对一组对象的功能(类中的方法)进行增强时,就可以使用该模式进行问题的解决。
装饰和继承都能实现一样的特点:进行功能的扩展增强。
有什么区别呢?
进行的继承,可能导致继承体系越来越臃肿。不够灵活。装饰比继承灵活。
例如:既然加入的都是同一种技术--缓冲。前一种是让缓冲和具体的对象相结合。可不可以将缓冲进行单独的封裝,哪个对象需要緩冲就将哪个对象和缓冲关联。
特点:装饰器和被装饰的类都必需所属同一个接口或者父类。
使用场景:
- 需要扩展一个类的功能,或给一个类增加附属功能;
- 需要动态的给一个对象增加功能,这些功能还可以动态的撤销;
- 需要为一批的兄弟类进行改装或加装功能。
类图:
在类图中一共有四个角色:
- Component抽象构件:一个接口或抽象类,就是定义我们最核心的对象。
- Component Component具体构件:最核心,最原始,最基本的接口或抽象类的实现,需要装饰的对象。
- Decorator装饰角色:一般是一个抽象类,实现接口或抽象方法,里面不一定有抽象的方法。在其中一定有一个private变量指向Component抽象构件。
- Concrete Decorator1具体装饰角色:Concrete Decorator1和Concrete Decorator2是具体装饰类,需要将最核心的,最原始的,最基本的东西装饰成其他的东西。
装饰模式通用模板:
public abstract class Component{//抽象构件类
//抽象的方法
public abstract void operate();
}
public class ConcreteComponent extends Component{//具体构件
//具体实现
@Override
public void operate() {
System.out.println("do something");
}
}
public abstract class Decorator extends Component{//抽象装饰者
private Component component = null;
//构造函数
public Decorator(Component component) {
this.component = component;
}
//委托给被装饰者执行
@Override
public void operate() {
this.component.operate();
}
//当只有一个装饰类时,可以不必设置抽象装饰类
}
public class ConcreteDecorator1 extends Decorator{
//构造
public ConcreteDecorator1(Component component) {
super(component);
// TODO Auto-generated constructor stub
}
//自己定义的装饰方法
private void method1() {
System.out.println("method1 装饰方法");
}
//重写operate方法
@Override
public void operate() {
this.method1();
super.operate();
}
}
public class ConcreteDecorator2 extends Decorator{
//构造
public ConcreteDecorator2(Component component) {
super(component);
// TODO Auto-generated constructor stub
}
//自己定义的装饰方法
private void method2() {
System.out.println("method2 装饰方法");
}
//重写operate方法
@Override
public void operate() {
//原始方法和装饰方法的执行顺序在具体类图中是固定的,可以通过方法的重载实现多种执行顺序。
super.operate();
this.method2();
}
}
//场景类
public class Client{
public static void main (String[] args) {
Component component = new ConcreteComponent();//生成具体构件
component = new ConcreteDecorator1(component);//进行第一次装饰
component = new ConcreteDecorator2(component);//进行第二次装饰
component.operate();
}
}