作用
装饰者模式的作用就是可以方便的为组件添加功能,例如买卷饼的时候,你肯定希望卷饼是按自己的口味卷的,要不要放鸡蛋,要不要加生菜,辣椒酱还是番茄酱,如果能自由搭配最好,写程序也是一样,如果有一堆零件,自由搭配肯定更灵活,所以装饰者存在的意义就是给基本组件附加功能。
应用场景
- io流(装饰者模式在实例化的时候,总是一个套一个,如下所示)
- File f=new File();
FileOutputStream fos=new FileOutputStream(f);
BufferedOutputStream out=new BufferedOutputStream(fos) ;
应用的设计原则
-
- 对扩展开放,对修改封闭
装饰者模式一经完工,无论后期增加组件,还是增加装饰物,都极为方便,而且不必修改原有的代码。
优点
- 组件功能搭配方式过多的时候,用装饰者模式可以动态装配,避免了类爆炸
- 当添加新的组件和装饰物的时候会变得很容易
缺点
-
- 设计装饰者要求组件和装饰物都必须有相同的类型,引入此模式必须注意
- 装饰者模式产生的小类过多,容易迷糊
- 虽然用继承容易把代码写死,但是装饰者中还是继承比较方便,最主要还是为了使类型统一
主要组成
一个超类 |
可以是接口,为了保证所以类的类型统一 |
组件 |
继承超类 |
抽象的装饰类 |
继承超类 |
装饰物 |
继承了装饰类,拥有和组件相同的方法,保留了超类的引用, 并且在方法内增加了新的功能 |
类图
下面是我程序的类图
源程序
大饼的超类
package decorator_03;
//超类是为了让所有的子类类型一致
public abstract class Pancake {//做一个大饼,有价格,有描述
String name;
public String getDescription() {
return name;
}
public abstract int cost();
}
大饼组件
package decorator_03;
public class BigPancake extends Pancake {//具体的大饼组件
public BigPancake() {
name = "bigpancake";
}
public int cost() {
return 4;
}
}
手抓饼组件
package decorator_03;
public class HandCake extends Pancake {//手抓饼组件
public HandCake() {
name = "handcake";
}
public int cost() {
return 3;
}
}
装饰者抽象类
package decorator_03;
public abstract class ExtraDecorator extends Pancake{
public abstract String getDescription() ;
public abstract int cost() ;
}
鸡蛋装饰者
package decorator_03;
public class EggDecorator extends ExtraDecorator {//加鸡蛋的装饰者
private Pancake pancake;
public EggDecorator(Pancake pancake) {
this.pancake = pancake;
}
public String getDescription() {
return pancake.getDescription() + "+egg";
}
public int cost() {
return pancake.cost() + 1;
}
}
火腿装饰者
package decorator_03;
public class SausageDecorator extends ExtraDecorator{//加火腿的装饰者
private Pancake pancake;
public SausageDecorator(Pancake pancake) {
this.pancake = pancake;
}
public String getDescription() {
return pancake.getDescription() + "+sausage";
}
public int cost() {
return pancake.cost() + 2;
}
}
客户端
package decorator_03;
public class Client {
public static void main(String[] args) {
Pancake cake=new HandCake();//实例化一个手抓饼
Pancake cake2=new EggDecorator(cake);//加鸡蛋
Pancake cake3=new SausageDecorator(cake2);//加火腿
System.out.println(cake3.getDescription()+" "+cake3.cost());
}
}
打印结果