继Java设计模式适配器模式后的装饰器模式来啦,让我们一起看看吧。 会了就当复习丫,不会来一起来看看吧。 很喜欢一句话:“八小时内谋生活,八小时外谋发展”。 如果你也喜欢,让我们一起坚持吧!!
共勉
😁
一张旧图,恍惚间念起旧人
上班族大多都有睡懒觉的习惯,每天早上上班时间都很紧张,于是很多人为了多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框等,都是装饰器模式。在我们自己行业就是这个东西得加需求啦
在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能。所有这些都可以釆用装饰器模式来实现。
装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
1、扩展一个类的功能。
2、动态增加功能,动态撤销。
就是主要为了方便扩展。
快餐店有炒面、炒饭这些快餐,可以额外附加鸡蛋、火腿、培根这些配菜,当然加配菜需要额外加钱,每个配菜的价钱通常不太一样,那么计算总价就会显得比较麻烦。
这是一个快餐店的例子,这么咋一看,感觉还可以,但是如果不再局限于炒饭FriedRice
和炒面FriedNoodies
中,想要做一些扩展,例如加一个炒粉Fried sweet potato powder
,就又要额外增加一个整体,再往下重复实现鸡蛋、培根等等的类。增加这么多,就会造成类爆炸,特别多,就非常不合适。
会产生过多的子类。欲知后事如何,请看下文👇。
接下来,我们用装饰器的模式来重构一下代码,看看会产生哪些方面的变化哈。也来一起看看装饰器模式的精髓。
不过图也要改变一下啦,变成这样子的啦:
我们先来讲讲这张图和上一张图的区别。
FriedRice和FriedNoodies
还是继承FastFoot
Egg和Bacon
不再位于 炒饭炒面下面,而是继承于抽象的配料类下,而配料类Garnish
又继承于FastFoot
。这么看好像还是少了点东西,结合代码我们一起来看一看。
我们把角色定位一下:
👇下面看代码一步一步实现看一下:
FastFoot
快餐接口:即抽象构件
//快餐接口
public abstract class FastFood {
private float price;
private String desc;
public FastFood() { }
public FastFood(float price, String desc) {
this.price = price;
this.desc = desc;
}
//set、get 方法
public void setPrice(float price) { this.price = price; }
public float getPrice() { return price; }
public String getDesc() { return desc; }
public void setDesc(String desc) { this.desc = desc; }
public abstract float cost(); //获取价格
}
FriedRice和FriedNoodies
即炒饭炒面 即具体构件
//炒饭
public class FriedRice extends FastFood {
public FriedRice() {
super(10, "炒饭");
}
// 获取价格
public float cost() {
return getPrice();
}
}
//炒面
public class FriedNoodles extends FastFood {
public FriedNoodles() {
super(12, "炒面");
}
// 获取价格
public float cost() {
return getPrice();
}
}
Garnish
即配料类 抽象装饰
public abstract class Garnish extends FastFood {
private FastFood fastFood;
public FastFood getFastFood() { return fastFood; }
public void setFastFood(FastFood fastFood) { this.fastFood = fastFood; }
public Garnish(FastFood fastFood, float price, String desc) {
super(price,desc);
this.fastFood = fastFood;
}
}
Egg和Bacon
类,即鸡蛋和培根为 具体装饰类
//鸡蛋配料
public class Egg extends Garnish {
public Egg(FastFood fastFood) { super(fastFood,1,"鸡蛋"); }
// 这里是返回了 炒饭加 鸡蛋的钱的
public float cost() { return getPrice() + getFastFood().getPrice(); }
@Override
public String getDesc() { return super.getDesc() + getFastFood().getDesc(); }
}
//培根配料
public class Bacon extends Garnish {
public Bacon(FastFood fastFood) { super(fastFood,2,"培根"); }
@Override
public float cost() { return getPrice() + getFastFood().getPrice(); }
@Override
public String getDesc() { return super.getDesc() + getFastFood().getDesc(); }
}
测试类
:
public class Client {
public static void main(String[] args) {
//点一份炒饭
FastFood food = new FriedRice();
//花费的价格
System.out.println(food.getDesc() + " " + food.cost() + "元");
System.out.println("========");
//点一份加鸡蛋的炒饭
FastFood food1 = new FriedRice();
food1 = new Egg(food1);
//花费的价格
System.out.println(food1.getDesc() + " " + food1.cost() + "元");
System.out.println("========");
//点一份加培根的炒面
FastFood food2 = new FriedNoodles();
food2 = new Bacon(food2);
//花费的价格
System.out.println(food2.getDesc() + " " + food2.cost() + "元");
}
}
这就解决了我们刚开始的一个问题,如果还需要进行扩张,需要增加一个炒河粉 那么只需要写一个炒河粉的类来继承FastFoot
快餐类即可,如需增加配料,也只要写个配料类来继承Garnish
配料类即可。其他代码均不用改变,完全符合开闭原则。也比原本减少了类的产生。😁
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
你卷我卷,大家卷,什么时候这条路才是个头啊。😇(还是直接上天吧)
有时候也想停下来歇一歇,一直做一个事情,感觉挺难坚持的。😁
你好,如果你正巧看到这篇文章,并且觉得对你有益的话,就给个赞吧,让我感受一下分享的喜悦吧,蟹蟹。🤗
如若有写的有误的地方,也请大家不啬赐教!!
同样如若有存在疑惑的地方,请留言或私信,定会在第一时间回复你。
持续更新中