设计模式———装饰模式
例子:成绩单报告
在面向对象的设计中,如果超过两层继承,可能就出设计问题了。这是经验总结,并非定论。继承层次越多,维护成本越多。
增加一个抽象类和两个实现类,其中Decorator的作用是封装SchoolReort类
抽象成绩单
//抽象成绩单
public abstract class SchoolReport{
public abstract void report();
public abstract void sign(String name);
}
具体的四年级成绩
public abstract FourthGradeSchoolReport extends SchoolReport{
public void report(){
System.out.println("尊敬的XX家长");
System.out.println("成绩如下");
System.out.println("语文xx");
// ...
}
public void sign(String name){
System.out.println("家长签名为:"+name);
}
}
修饰的抽象类
// 修饰的抽象类
public abstract class Decorator extends SchoolReport{
private SchoolReport sr;
public Decorator(SchoolReport sr){
this.sr = sr;
}
// 报告成绩
public void report(){
this.sr.report();
}
//家长签名
public void sign(String name){
this.sr.sign(name);
}
}
最高成绩修饰
public class HighScoreDecorator extends Decorator {
public HighScoreDecorator(SchoolReport sr){
super(sr);
}
private void reportHighScore(){
System.out.println("最高成绩是:XX");
}
public void report(){
this.reportHighScore();
super.report();
}
}
排名情况修饰
public class SortDecorator extends Decorator {
public SortDecorator(SchoolReport sr){
super(sr);
}
public void reportSort(){
System.out.println("排名情况是xx");
}
@Override
public void report(){
this.reportSort();
super.report();
}
}
查看成绩单
public class Father{
public static void main(String[] args) {
//把成绩单拿过来
SchoolReport sr;
//原装的成绩单
sr = new FourthGradeSchoolReport();
//加了最高分说明的成绩单
sr = new HighScoreDecorator(sr);
// 加了排名的说明
sr = new SortDecorator(sr);
//看成绩单
sr.report();
sr.sign("name");
}
}
装饰模式的定义
Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
四个角色说明
- component抽象构件
- component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象
- 在装饰模式中,必然有一个最基本,最核心,也就是最原始的对象
- concreteComponent具体构建
- concreteComponent是最核心,最原始,最基本的接口或抽象类的实现,要装饰的就是它
- Decorator装饰角色
- 一般是一个抽象类,实现接口或者抽象方法
- 它的属性里必定有一个private变量指向Component抽象构建
- ConcreteDecorator具体装饰角色
- ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,要把最原始,最基本,最核心的进行装饰
抽象构件
public abstract class Component{
//抽象的方法
public abstract void operate();
}
具体构件
public class ConcreteComponent extends Component {
// 具体实现
public void operate(){
// code to do something
System.out.println("doSomethin");
}
}
抽象装饰者
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);
}
//定义自己的修饰方法
public void method(){
//code to do something
}
public void operate(){
this.method();
super.operate();
}
}
public class ConcreteDecorator2 extends Decorator{
public ConcreteDecorator2(Component component){
super(component);
}
//定义自己的修饰方法
public void method(){
//code to do something
}
public void operate(){
this.method();
super.operate();
}
}
场景类
public class Client{
public static void main(String[] args) {
Component component = new ConcreteComponent();
// 第一次修饰
component = new ConcreteDecorator1(component);
// 第二次修饰
component = new ConcreteDecorator2(component);
//运行结果
component.operate();
}
}
装饰模式的优缺点
装饰模式的优点
- 装饰类和被装饰类可以独立发展,不会相互耦合。
- Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能,Decorator也不用知道具体的构件
- 装饰模式是继承关系的一个替代方案
- 装饰类Decorator不管装饰多少层,返回的对象还是Component,实现的还是is-a关系
- 装饰模式可以动态地扩展一个实现类的功能,这不需要多说,装饰模式的定义就是如此
装饰模式的缺点
- 多层的装饰是比较复杂的
- 尽量减少装饰类的数量,一遍降低系统的复杂度
装饰模式的使用场景
- 需要扩展一个类的功能,或给出一个类增加附加功能
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销
- 需要为一批的兄弟类进行改装或加装功能,当然是首选装饰模式