1.定义:装饰模式是动态的扩展一个对象的功能,而不需要改变原始类代码的一种成熟模式。
2.GOF引用:动态的给对象添加一些额外的职责。就功能来说装饰模式相比生成子类更为灵活。(以某个对象为单位动态增加功能)
3.理解:
“具体组件”类和“具体装饰”类是该模式中最重要的两个角色。前者对应的实例成为“被装饰者”,后者对应的实例成为“装饰者”。
“具体装饰”类需要包含有“具体组件”类的一个实例(被装饰者)的引用,以便装饰“被装饰者”。
装饰模式最重要的一点就是“具体组件”和“装饰”都是“抽象组件”的子类。因此,“抽象组件”声明的引用可以指向“具体组件”也可以指向“装饰者”。调用子类中的方法或者修正方法可以进行原型输出或者装饰输出。
其次,“装饰者”由于是“抽象组件”的子类,因此也可以把它作为“被装饰者”,这意味着具体装饰类来“装饰”具体装饰类的实例。
4.类图:
抽象组件:是一个抽象类。定义了“被装饰类”需要进行“修饰”的方法
具体组件:抽象组件的一个子类,具体组件的实例称作“被装饰者”。
装饰:抽象组件的一个子类,但装饰还包含一个抽象组件声明的变量以保存“被装饰者”的引用。装饰可以是抽象类也可以是一个非抽象类,如果是非抽象类,那么该类的实例称作“装饰者”。
具体装饰:装饰的一个非抽象子类,其实例称作“装饰者”。
5. 装饰模式举例(代码示例)
问题描述如下:动态的为麻雀类的某一个对象增加功能(安装一对智能电子翅膀)
类图:
注意事项:Decorator类中的Bird属性是protected修饰。若只有一个具体装饰列,则可以改为private修饰。
SparrowDecorator类的eleFly方法访问权限设置为private,其目的是使得客户端程序只有调用fly()方法才可以使用eleFly方法。
具体代码如下:
package cn.ch;
public abstract class Bird {
public abstract int fly();
}
package cn.ch;
public class Sparrow extends Bird {
public final int DISTANCE=100;
public int fly() {
return DISTANCE;
}
}
package cn.ch;
public abstract class Decorator extends Bird {
protected Bird bird;
public Decorator() {
super();
}
public Decorator(Bird bird) {
super();
this.bird = bird;
}
}
package cn.ch;
public class SparrowDecorator extends Decorator {
public final int DISTANCE=50; //eleFly()方法能飞50米
public SparrowDecorator() {
super();
// TODO 自动生成的构造函数存根
}
public SparrowDecorator(Bird bird) {
super(bird);
// TODO 自动生成的构造函数存根
}
public int fly() {
int distance=0;
distance=bird.fly()+eleFly(); //委托被装饰者bird调用fly(),然后再调用eleFly()
return distance;
}
private int eleFly() { //装饰者新添加的方法
return DISTANCE;
}
}
package cn.ch;
public class Application{
public static void main(String[] args) {
Application client=new Application();
Bird sparrow=new Sparrow(); //sparrow只能飞行100米
Bird sparrowDecorator1=new SparrowDecorator(sparrow); //sparrowDecorator1能飞行150米
Bird sparrowDecorator2=new SparrowDecorator(sparrowDecorator1); //sparrowDecorator2能飞行200米
client.needBird(sparrowDecorator1);
client.needBird(sparrowDecorator2);
}
public void needBird(Bird bird){
int flyDistance=bird.fly();
System.out.println("这只鸟能飞行"+flyDistance+"米");
}
}
装饰模式的优点:
1. 被装饰者和装饰者是松耦合的关系。
2. 装饰模式满足“开闭原则”。
3. 可以使用多个具体装饰来装饰具体组件的实例。
适合使用观察者模式的情景:
1. 程序希望动态的增加类的某个对象的功能,而又不影响到类的其他对象。
2. 采用继承增强对象功能不利于系统的扩展和维护。