装饰者模式,动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。
示例:
package Decorator;
/**
* 每个人都有展示的功能
*
*/
public interface Person {
public void show();
}
package Decorator;
/**
* Student类
*
*/
public class Student implements Person {
public void show() {
System.out.println("我是一个学生");
}
}
假如不想更改原类的结构,想对学生展示方法show()增加一系列的功能,即运用装饰者模式。
原Person,Studnet类不变
构建以下类:
package newDecorator;
/**
* 好学生
*
*/
public class GoodStudent extends Student {
@Override
public void show() {
Student s = new Student();// 持有引用类的对象(被装饰者)
s.show();
System.out.println("我的成绩好"); // 扩展的功能(装饰项)
}
}
package newDecorator;
/**
* 坏学生
*
*/
public class BadStudnet extends Student {
public void show() {
Student s = new Student();// 持有引用类的对象(被装饰者)
s.show();
System.out.println("我的成绩不好"); // 扩展的功能(装饰项)
}
}
package newDecorator;
/**
* 测试类 通过实例化不同得子类调用来调用show方法来实现不同的装饰目的
*/
public class Main {
public static void main(String[] args) {
/*
* GoodStudent1 p = new GoodStudent1();
*
* p.show();
*/
BadStudnet b = new BadStudnet();
b.show();
}
}
这样就可以在不更改原类的结构来进行扩展。
优点
1、装饰者模式可以提供比继承更多的灵活性
2、可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。
3、通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
4、具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。
缺点
1、会产生很多的小对象,增加了系统的复杂性
2、这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。装饰着模式适用的场景
1、在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
2、需要动态的给一个对象增加功能,这些功能也可以动态地被撤销。当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。