1. 什么是装饰者模式
装饰者模式就是动态的给某个对象扩展一些额外的功能。装饰模式相比生成子类更为灵活。
2. 装饰者模式中都有什么角色
2.1. 抽象组件(Component)
给出一个抽象接口,用来规范准备接收附加功能的对象
2.2. 具体组件(ConcreteComponent)
将要被附加功能的类,实现抽象组件角色的接口
2.3. 抽象装饰者组件(Decorator)
是抽象组件的一个子类,是“装饰者”角色,其作用是装饰具体组件,因此,抽象装饰者角色需要包含抽象组件的引用。可以是抽象类,也可以是非抽象类。
2.4. 具体装饰者组件(ConcreteDecorator)
实现抽象装饰者角色,负责对具体组件添加额外功能
3. 类图
装饰者模式1.jpg4. 代码描述
装饰模式是动态的扩展一个对象的功能,而不需要改变原始类代码的一种成熟模式。
在许多设计中,可能需要改进对某个对象的功能,而不是该类所有的对象。
- 例如:小鸟类的实例对象可以连续飞行100米,我们创建了5只小鸟,想让其中一只可以连续飞行200米,其他鸟还是100米。
- 这时我们可以给这只小鸟装一个加速器,这只小鸟就可以借助加速器比别的小鸟多飞100米,如果装两个加速器,小鸟就可以飞300米。
- 这就是我们设计装饰者模式的初衷——改变类的某个对象的功能
4.1. 抽象组件
public abstract class Bird {
public abstract int fly();
}
4.2. 具体组件
具体组件是抽象组件的一个子类,具体组件的实例称为“被装饰者”。
public class SuperBird extends Bird {
public final int DISTANCE = 100;
@Override
public int fly() {
return DISTANCE;
}
}
4.3. 抽象装饰者组件
抽象装饰组件是抽象组件的一个子类,其作用是装饰具体组件。因此,抽象装饰组件需要包含“被装饰者”的引用。而且,抽象装饰组件本身也是抽象组件的子类,即也是具体组件的角色,不同之处在于,抽象装饰组件额外提供了一些方法。
public abstract class Faster extends Bird {
Bird bird;//被装饰者
public Faster(Bird bird) {
this.bird = bird;
}
@Override
public int fly() {
return bird.fly();
}
public abstract int eleFly();//用于修饰fly()方法,具体行为由装饰者去实现
}
4.4. 具体装饰组件
根据具体的问题,具体装饰组件用新的方法去装饰具体组件。
public class FasterDecorator extends Faster {
public final int ELEDISTANCE = 100;//加速器能多飞100米
FasterDecorator(Bird bird) {
super(bird);
}
@Override
/**
* 被装饰的方法
*/
public int fly() {
return bird.fly() + eleFly();
}
@Override
/**
*具体装饰者重写装饰者中用于装饰的方法
*/
public int eleFly() {
return ELEDISTANCE;
}
}
4.5. 测试
public class Test {
public static void main(String[] args) {
Bird bird=new SuperBird() ;
System.out.println("没有安装加速器的小鸟飞行距离:"+bird.fly());
bird=new FasterDecorator(bird);
System.out.println("安装了1个加速器的小鸟飞行距离:"+bird.fly());
bird=new FasterDecorator(bird);
System.out.println("安装了2个加速器的小鸟飞行距离:"+bird.fly());
bird=new FasterDecorator(bird);
System.out.println("安装了3个加速器的小鸟飞行距离:"+bird.fly());
}
}
运行结果
没有安装加速器的小鸟飞行距离:100
安装了1个加速器的小鸟飞行距离:200
安装了2个加速器的小鸟飞行距离:300
安装了3个加速器的小鸟飞行距离:400
5. 使用多个装饰器
由于抽象装饰组件本身也是抽象组件的一个子类,所以“装饰者”本身也可以成为一个“被装饰者”,这意味着我们可以使用多个具体装饰类来装饰具体组件的实例。
- 比如我们需要一个可以飞行150米的鸟,那么就不必修改现有的类,只需要再添加一个具体装饰即可。
public class FasterDecorator2 extends Faster{
public final int ELEDISTANCE = 50;//加速器能多飞50米
FasterDecorator2(Bird bird) {
super(bird);
}
@Override
/**
* 被装饰的方法
*/
public int fly() {
return bird.fly() + eleFly();
}
@Override
/**
*具体装饰者重写装饰者中用于装饰的方法
*/
public int eleFly() {
return ELEDISTANCE;
}
}
Bird bird=new SuperBird() ;
bird=new FasterDecorator(bird);
bird=new FasterDecorator(bird);
bird=new FasterDecorator(bird);
bird=new FasterDecorator2(bird);
6. 装饰模式的优势
-
被装饰者和装饰者是松耦合关系,由于抽象装饰组件仅仅依赖于抽象组件,因此,具体装饰只需要知道它要装饰的对象是抽象组件的某一个实例,不需要知道是哪一个具体子类。
-
装饰模式满足“开-闭”原则,用户不必修改具体组件,就可以增加新的针对该具体组件的具体装饰。
-
可以使用多个具体装饰来装饰具体组件的实例。
网友评论