【设计模式】装饰者模式。
我们先来看一个快餐店的例子:
快餐店有炒面、炒饭这些快餐,可以额外附加鸡蛋、火腿、培根这些配菜,当然加配菜需要额外加钱,每个配菜的价钱通常不太一样,那么计算总价就会显得比较麻烦。
使用继承的方式存在的问题:
- 扩展性不好
如果要再加一种配料(火腿肠),我们就会发现需要给FriedRice(炒饭)和FriedNoodles(炒面)分别定义一个子类。如果要新增一个快餐品类(炒河粉)的话,就需要定义更多的子类。- 产生过多的子类
这时就可以采用装饰模式:
- 指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
类图如下:
/**
* @Version: 1.0.0
* @Author: Dragon_王
* @ClassName: Bacon
* @Description: 培根类
* @Date: 2023/12/24 15:20
*/
public class Bacon extends Garnish{
public Bacon(FastFood fastFood){
super(fastFood,2,"培根");
}
@Override
public String getDesc() {
return super.getDesc() + getFastFood().getDesc();
}
@Override
public float cost() {
return getPrice() + getFastFood().cost();
}
}
=========================
/**
* @Version: 1.0.0
* @Author: Dragon_王
* @ClassName: Egg
* @Description: 鸡蛋类(具体装饰者角色)
* @Date: 2023/12/24 15:15
*/
public class Egg extends Garnish {
public Egg(FastFood fastFood){
super(fastFood,1,"鸡蛋");
}
@Override
public float cost() {
return getPrice() + getFastFood().cost();
}
}
=========================
/**
* @Version: 1.0.0
* @Author: Dragon_王
* @ClassName: FastFood
* @Description: 快餐类
* @Date: 2023/12/24 15:06
*/
public abstract class FastFood {
private float price;// 价格
private String 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 FastFood() {
}
public FastFood(float price, String desc) {
this.price = price;
this.desc = desc;
}
public abstract float cost();
}
=========================
/**
* @Version: 1.0.0
* @Author: Dragon_王
* @ClassName: FireNoodles
* @Description: 炒面
* @Date: 2023/12/24 15:10
*/
public class FireNoodles extends FastFood{
public FireNoodles() {
super(12,"炒面");
}
@Override
public float cost() {
return getPrice();
}
}
=====================
/**
* @Version: 1.0.0
* @Author: Dragon_王
* @ClassName: FireRice
* @Description: 炒饭类
* @Date: 2023/12/24 15:09
*/
public class FireRice extends FastFood{
public FireRice(){
super(10,"炒饭");
}
@Override
public float cost() {
return getPrice();
}
}
==========================
/**
* @Version: 1.0.0
* @Author: Dragon_王
* @ClassName: Darnish
* @Description: 装饰者类(抽象装饰者角色)
* @Date: 2023/12/24 15:12
*/
public abstract class Garnish extends FastFood{
private FastFood fastFood;
public FastFood getFastFood() {
return fastFood;
}
public void setFastFood(FastFood fastFood) {
this.fastFood = fastFood;
}
@Override
public String getDesc() {
return super.getDesc() + getFastFood().getDesc();
}
public Garnish(FastFood fastFood, float price, String desc) {
super(price, desc);
this.fastFood = fastFood;
}
}
=============================
/**
* @Version: 1.0.0
* @Author: Dragon_王
* @ClassName: Client
* @Description: 测试类
* @Date: 2023/12/24 15:22
*/
public class Client {
public static void main(String[] args) {
//点一份炒饭
FastFood food = new FireRice();
//花费的价格
System.out.println(food.getDesc() + " " + food.cost() + "元");
System.out.println("========");
//点一份加鸡蛋的炒饭
FastFood food1 = new FireRice();
food1 = new Egg(food1);
//花费的价格
System.out.println(food1.getDesc() + " " + food1.cost() + "元");
System.out.println("========");
//点一份加培根的炒面
FastFood food2 = new FireNoodles();
food2 = new Bacon(food2);
//花费的价格
System.out.println(food2.getDesc() + " " + food2.cost() + "元");
}
}
- IO流中的包装类使用到了装饰者模式。BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter。
- 我们以BufferedWriter举例来说明,先看看如何使用BufferedWriter
public class Demo {
public static void main(String[] args) throws Exception{
//创建BufferedWriter对象
//创建FileWriter对象
FileWriter fw = new FileWriter("C:\\Users\\Think\\Desktop\\a.txt");
BufferedWriter bw = new BufferedWriter(fw);
//写数据
bw.write("hello Buffered");
bw.close();
}
}
使用起来感觉确实像是装饰者模式,接下来看它们的结构:
小结:
? BufferedWriter使用装饰者模式对Writer子实现类进行了增强,添加了缓冲区,提高了写数据的效率。
静态代理和装饰者模式的区别:
以上就是设计模式之装饰者模式的讲解。