[原创]装饰模式(java版)
1、什么是装饰模式?
动态的给一个对象添加额外的一些功能的方式,就增加功能来说,比子类继承要更加灵活。
添加额外功能可以通过set方法的方式传递进来一个需要被修饰的对象,或者通过构造函数传参的方式传入要被修饰的对象:
java代码描述:
//抽象构建
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;
}
//或者也可以通过setComponent方法传递被修饰者
// public void setComponent(Component component){
// this.component = component;
// }
//委托给被修饰者对象执行
@Override
public void operate(){
this.component.operate();
}
}
//具体的装饰类
public class ConcreteDecorator1 extends Decorator{
//传递被修饰者
public ConcreteDecorator1(Component _component){
super(_component);
}
//或者也可以通过setComponent方法传递被修饰者
// public void setComponent(Component component){
// this.component = component;
// }
//定义增加的功能或者说修饰的行为
private void method1(){
System.out.println("method1 修饰");
}
//重写父类的operate方法
public void operate(){
//这里我是让修饰行为在被修饰对象所作动作之前进行修饰执行。
//当然也可以调整修饰的顺序
this.method1();
super.operate();
}
}
这里还可以有另外一个或者多个具体的装饰类,比如:
public class ConcreteDecorator2 extends Decorator{....}
装饰模式的通用类图如下:
2、装饰模式的应用场景:
当你需要动态的增加一个类的功能的时候,就需要使用装饰模式。
3、装饰模式和子类继承的区别:
首先装饰模式可以动态的增加或者删除一个功能,对于被装饰对象或者其他装饰类不会有影响;但如果是子类继承来增加或者删除功能的话,会修改原来代码或者产生新的子类,这样可能会对其他类产生影响,并且导致类膨胀,当类过多的时候,就不利于管理和维护。
4、为什么要使用装饰模式(或者说装饰模式的好处)?
①当修改代码时,装饰对象和被装饰对象互不影响;
②装饰对象可以动态的添加功能,弥补了子类继承静态增加功能的缺陷;
5、装饰模式的缺点?
多层装饰是很复杂的,应该减少装饰类数量;比如当多层装饰的时候,最里层装饰类出错,那么去定位这个错误就可能会产生很大的工作量。
6、为什么子类继承增加或者扩展功能会导致类膨胀?
比如说:写一个person类,现在要对该类进行修饰。我们要一个先穿衣服再穿裤子的修饰功能,我首先写一个穿衣服的修饰类继承该person,然后再写一个穿裤子的类继承穿衣服的修饰类,这样就完成了先穿衣服再穿裤子的修饰功能。但如果现在我们还需要一个先穿裤子再穿衣服的修饰功能,那么我们可能需要重新去写一个裤子修饰类去继承person类,然后写一个衣服修饰类去继承裤子修饰类。当这样的需求还有很多的时候,那么就会产生很多的子类,从而导致类膨胀,不利于代码的管理和维护。