设计模式之装饰者模式笔记
- 说明
- Decorator(装饰)
- 目录
- 装饰者模式示例类图
- 快餐类
- 炒饭类
- 炒面类
- 装饰者类
- 鸡蛋类
- 培根类
- 测试类
说明
记录下学习设计模式-装饰者模式的写法。JDK使用版本为1.8版本。
Decorator(装饰)
意图:动态地给一个对象添加一些额外的职责。
结构:
其中:
- Component定义一个对象接口,可以给这些对象动态地添加职责。
- ConcreteComponent定义一个对象,可以给这个对象添加一些职责。
- Decorator维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
- ConcreteDecorator向组件添加职责。
适用性:
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤销的职责。
- 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是,由于类定义被隐藏,或类定义不能用于生成子类。
目录
装饰者模式示例类图
快餐店有炒面、炒饭这些快餐,可以额外附加鸡蛋、火腿、培根这些配菜,当然加配菜需要额外加钱,每个配菜的价钱通常不太一样,那么计算总价就会显得比较麻烦。
以该UML类图实现装饰者模式示例。
快餐类
package com.example.deesign_patterns.decorator;
//快餐类
public abstract class FastFood {
private float price;//价格
private String desc;//描述
public FastFood() {
}
public FastFood(float price, String desc) {
this.price = price;
this.desc = desc;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public abstract float cost();//计算价格
}
炒饭类
package com.example.deesign_patterns.decorator;
//炒饭类
public class FriedRice extends FastFood{
public FriedRice(){
super(10,"炒饭");//设置炒饭的价格为10元
}
@Override
public float cost() {
return getPrice();
}//获取炒饭的价格
}
炒面类
package com.example.deesign_patterns.decorator;
//炒面类
public class FriedNoodles extends FastFood{
public FriedNoodles(){
super(12,"炒面");//设置炒面的价格为12元
}
@Override
public float cost() {
return getPrice();
}//获取炒面的价格
}
装饰者类
package com.example.deesign_patterns.decorator;
//装饰者类
public abstract class Garnish extends FastFood{
//声明快餐类的变量
private FastFood fastFood;
public FastFood getFastFood() {
return fastFood;
}
public void setFastFood(FastFood fastFood) {
this.fastFood = fastFood;
}
public Garnish(float price, String desc, FastFood fastFood) {
super(price, desc);
this.fastFood = fastFood;
}
}
鸡蛋类
package com.example.deesign_patterns.decorator;
//鸡蛋类
public class Egg extends Garnish{
public Egg(FastFood fastFood) {
super(1, "鸡蛋", fastFood);//设置鸡蛋的价格为1元
}
@Override
public float cost() {
return getPrice()+getFastFood().cost();//计算鸡蛋的价格加炒饭或者炒面的价格
}
@Override
public String getDesc() {
return super.getDesc()+getFastFood().getDesc();
}
}
培根类
package com.example.deesign_patterns.decorator;
//培根类
public class Bacon extends Garnish{
public Bacon(FastFood fastFood) {
super(2, "培根", fastFood);//设置培根的价格为1元
}
@Override
public float cost() {
return getPrice()+getFastFood().cost();//计算培根的价格加炒饭或者炒面的价格
}
@Override
public String getDesc() {
return super.getDesc()+getFastFood().getDesc();
}
}
测试类
package com.example.deesign_patterns.decorator;
//测试类
public class Client {
public static void main(String[] args) {
//点一份炒饭
FastFood food=new FriedRice();
System.out.println(food.getDesc()+" "+food.cost()+"元");
System.out.println("=============================");
//在炒饭中加入鸡蛋
food=new Egg(food);
System.out.println(food.getDesc()+" "+food.cost()+"元");
System.out.println("=============================");
//在炒饭中再加入鸡蛋
food=new Egg(food);
System.out.println(food.getDesc()+" "+food.cost()+"元");
System.out.println("=============================");
//在炒饭中再加入培根
food=new Bacon(food);
System.out.println(food.getDesc()+" "+food.cost()+"元");
}
}
好处:
- 装饰者模式可以带来比继承更加灵活性的扩展功能,使用更加方便,可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化的结果。装饰者模式比继承更具良好的扩展性,完美的遵循开闭原则,继承是静态的附加责任,装饰者模式则是动态地附加责任。
- 装饰类和被装饰类可以独立发展,不会相互耦合,装饰者模式是继承的一个替代模式,装饰者模式可以动态扩展一个实现类的功能。
JDK源码解析:
IO流中的包装类使用到了装饰者模式。BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter。
小结:BufferedWriter使用装饰者模式对Writer子实现类进行了增强,添加了缓冲区,提高了写数据的效率。