内容简介:装饰模式也算一种比较常见的设计模式,工作过程中很少刻意的去实现这种模式,因为这种模式也会带来一些问题。比如小类太多,组织起来比较麻烦,对客户端完全可见,如果不了解各个类的功能会很乱等等当然也有很多优点: 可以动态的给类增加一些职责,增加功能更加灵活,比起继承来说也更加具有弹性
装饰模式也算一种比较常见的设计模式,工作过程中很少刻意的去实现这种模式,因为这种模式也会带来一些问题。
比如小类太多,组织起来比较麻烦,对客户端完全可见,如果不了解各个类的功能会很乱等等
当然也有很多优点: 可以动态的给类增加一些职责,增加功能更加灵活,比起继承来说也更加具有弹性
下面我们来看看它究竟是什么样子的
场景设置
以买车业务模型为例(本人未买过车,业务场景纯属臆想)
车里面还有很多装备可以选择,根据不同的选择装饰决定最后到手的价格:
商品 | 价格 |
---|---|
裸车 | 100000 |
加热座椅(可选) | 4000 |
真皮内饰(可选) | 8000 |
蹦迪音响(可选) | 5000 |
第一版本实现(我们在一个类里面完成)
package car; public class Car { //总价 private int allPrice = 0; //裸车价格 --实际数值从数据库查询,此处略 private int nakedPrice = 100000; //加热座椅 private int heatedSeat = 4000; //真皮内饰 private int dermalInteriors = 8000; //蹦迪音响 private int bengdiSound = 5000; public Car() { this.allPrice += this.nakedPrice; } /** * 添加真皮座椅 */ public void addHeatedSeat() { this.allPrice += this.heatedSeat; } /** * 添加真皮内饰 */ public void addDermalInteriors() { this.allPrice += this.dermalInteriors; } /** * 添加蹦迪音响 */ public void addBengdiSound() { this.allPrice += this.bengdiSound; } /** * 获取总价 * * @return */ public int cost() { return this.allPrice; } } 复制代码
客户端调用:
package car; public class Main { public static void main(String[] args) { Car car = new Car(); car.addBengdiSound(); System.out.println("总花费价格:" + car.cost()); } } 复制代码
output:
花费价格105000 复制代码
看起来很简洁呢,并且也很好的实现了功能
首先这是我们的场景足够的简单,所涉及的配套组件也比较少,实际中可能针对某个方法可能有很复杂的获取和计算逻辑,组件也会有很多种选择,会造成类爆炸,无法继续维护下去
如果我们使用装饰模式,会带来什么改变呢,会给我们带来什么样的体验呢
设计:
实现:
声明抽象类(被装饰者和装饰者继承此类,目的对实现方法进行规正)
package car; public abstract class Car { public String name; public abstract String cost(); } 复制代码
主角:被装饰者类-裸车
package car; /** * 被装饰的类 -> 裸车 */ public class NakeCar extends Car { //裸车价格 --实际数值从数据库查询,此处略 private int nakedPrice = 100000; public NakeCar() { this.name = "裸车"; } /** * 获取总价 * * @return */ public String cost() { return this.name + ":" + this.nakedPrice; } } 复制代码
具体装饰类:
加热座椅
package car; /** * 装饰组件 */ public class HeatedSeat extends Car { //加热座椅 private int heatedSeat = 4000; //汽车对象 private Car car; public HeatedSeat(Car car) { this.name = "加热座椅"; this.car = car; } /** * 获取价格 * * @return */ public String cost() { //todo return this.car.cost() + "||" + this.name + ":" + this.heatedSeat; } } 复制代码
真皮内饰
package car; public class DermalInteriors extends Car { //真皮内饰 private int dermalInteriors = 8000; //汽车对象 private Car car; public DermalInteriors(Car car) { this.name = "真皮内饰"; this.car = car; } /** * 获取价格 * * @return */ public String cost() { //todo return this.car.cost() + "||" + this.name + ":" + this.dermalInteriors; } } 复制代码
蹦迪音响
package car; public class BengdiSound extends Car { //蹦迪音响 private int bengdiSound = 5000; //汽车对象 private Car car; public BengdiSound(Car car) { this.name = "蹦迪音响"; this.car = car; } /** * 获取价格 * * @return */ public String cost() { //todo return this.car.cost() + "||" + this.name + ":" + this.bengdiSound; } } 复制代码
客户端调用:
package car; public class Main { public static void main(String[] args) { NakeCar car = new NakeCar(); HeatedSeat heatedSeat = new HeatedSeat(car); BengdiSound bengdiSound = new BengdiSound(heatedSeat); System.out.println("总花费价格:" + bengdiSound.cost()); } } 复制代码
output:
总花费价格:裸车:100000||加热座椅:4000||蹦迪音响:5000 复制代码
总结
-
装饰模式的优点: 可以为已有的功能(被装饰对象)动态的添加功能,简化原有类。在我们的例子中, 裸车是主类,相当于业务中的核心,而一些动态的组件可以根据实际情况使用,也就相当于我们业务线中的附属拓展功能。
主逻辑和拓展逻辑的区分会使我们的代码更具拓展性。
-
装饰模式的缺点: 我们可以看到装饰模式的引入会增多类的数量,以及客户端的使用会有复杂度上升。装饰模式的类依赖特定的类型,需要严格遵守规约(抽象类的约束)
更多精彩内容关注公众号:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- django基础教程第三讲-路由和模板
- 应用编程基础课第三讲:Go编程基础
- 应用编程基础课第三讲:Go编程基础
- java爬虫系列第三讲-获取页面中绝对路径的各种方法
- 挑战全网最幽默的Vuex系列教程:第三讲 Vuex旗下的Mutation
- (第三讲)使用JUnit对Spring Boot中的Rest Controller进行单元测试
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。