设计模式-装饰模式
文章图片
结构图解释:
Component 可以是接口,也可以是抽象类,目的是指明Operation(),也就是规范要做什么。
ConcreteComponent 一个类,继承或者实现Component。是被装饰的代表,例如饭,奶茶。
Decorator类 装饰类,内部一定有Component或者ConcreteComponent的属性,表明用于装饰谁(扩展谁)。
ConcreteDecoratorA,ConcreteDecoratorB 我理解是各种装饰物(扩展)
如果只有一个ConcreteComponent而没有抽象的Component,那么Decorator类可以是ConcreteComponent的子类 何谓装饰模式? 例如,我现在有碗白饭,这饭上可以放土豆丝,放白菜,放豆干,放鸭腿,这就是鸭腿饭了。 那我放土豆丝,放白菜,放鸡腿,放豆干,这就是鸡腿饭了。 放不同的配菜,就是不同的套餐,如果我现在的菜单上有下述几种套餐: 鸡腿饭(鸡腿+青菜+香干) 肉丝饭(肉丝+青菜+香干) 大排饭(大排+青菜+香干) 鸭腿饭(鸭腿+青菜+香干) 东坡肉饭(东坡+青菜+香干) 要实现这几种饭 先用最容易想到的方式实现,每种套餐创建一个类,那么就有鸡腿饭类,肉丝饭类,大排饭类... 如果我现在鸡腿饭+一个大排你怎么办? 难道在创建一个鸡腿饭+一个大排的类? 那如果我要再加一个东坡肉呢?再加一个鸭腿呢?(这真有钱啊) 现在就发现我们这个实现方式就并不合适了。 我们先来分析一下,不同套餐其实就是不同的配菜加米饭对不对,像不像再给米饭的基础上一直叠加东西。 用装饰模式代码实现如下
/** * SX小吃 我这里卖 * 鸡腿饭(鸡腿+青菜+香干) * 肉丝饭(肉丝+青菜+香干) * 大排饭(大排+青菜+香干) * 鸭腿饭(鸭腿+青菜+香干) * 东坡肉饭(东坡+青菜+香干) * @author wrj * @description * @Date 2021/12/1 2:37 下午 */
abstract class Food { public abstract void has(); }//米饭 class Rice extends Food{@Override public void has() { System.out.println("有米饭"); } }//装饰类 abstract classFoodDecorator extends Food{public Food food; public void addFood(Food food){ this.food = food; }@Override public void has() { food.has(); } }//鸡腿 class Drumstick extends FoodDecorator{@Override public void has() { System.out.println("有鸡腿"); super.has(); } }//肉丝 class ShreddedMeat extends FoodDecorator{@Override public void has() { System.out.println("有肉丝"); super.has(); } }//大排 class PorkRibs extends FoodDecorator{@Override public void has() { System.out.println("有大排"); super.has(); } }//青菜 class Vegetable extends FoodDecorator{@Override public void has() { System.out.println("有青菜"); super.has(); } }//豆干 class DriedBeanCurd extends FoodDecorator{@Override public void has() { System.out.println("有豆干"); super.has(); } }public class SXFood {public static void main(String[] args) { //标准鸡腿饭的构建过程 System.out.println("鸡腿饭:\r\n"); Rice 米饭 = new Rice(); DriedBeanCurd 豆干 = new DriedBeanCurd(); Vegetable 青菜 = new Vegetable(); Drumstick 鸡腿 = new Drumstick(); 鸡腿.addFood(青菜); 青菜.addFood(豆干); 豆干.addFood(米饭); 鸡腿.has(); //特殊需求 鸡腿饭+大排 System.out.println("鸡腿饭+大排:\r\n"); Rice 米饭1 = new Rice(); DriedBeanCurd 豆干1 = new DriedBeanCurd(); Vegetable 青菜1 = new Vegetable(); Drumstick 鸡腿1 = new Drumstick(); PorkRibs 大排 = new PorkRibs(); 鸡腿1.addFood(大排); 大排.addFood(青菜1); 青菜1.addFood(豆干1); 豆干1.addFood(米饭1); 鸡腿1.has(); } }
【设计模式-装饰模式】最后输出:
文章图片
这种场景就适合用装饰模式了。回过头来再看装饰模式的概念: 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。 上面的鸡腿饭+大排的场景就体现了动态添加的特性以及为什么比子类更灵活因为我们不用一直生成子类,我们可以任意加东西来实现功能 可以看到 不同的搭配最终组合成了不同的套餐,这样不管有什么奇葩的需求,都不用改类,只需要改装饰的内容和顺序即可。 这也体现了开闭原则,不用改变基础的类,只需要改变使用方法即可。 需要注意装饰的顺序,顺序地不同,产生的结果也是不同的。这点需要注意
总结:
装饰模式是为已有功能动态地添加更多功能的一种方式,当系统需要新功能时,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为。
在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要(参考鸡腿饭加一个大排的场景)。
装饰模式提供了一个非常好的解决办法,它把每个要装饰的功能放在单独的类中。并让这个类包装它所要装饰的对象。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象。
优点:把类中的装饰功能从类中搬移出去,简化原有的类。有效地把类的核心职责和装饰功能区分开。
推荐阅读
- --木木--|--木木-- 第二课作业#翼丰会(每日一淘6+1实战裂变被动引流# 6+1模式)
- 设计模式-代理模式-Proxy
- 【译】Rails|【译】Rails 5.0正式发布(Action Cable,API模式等)
- java静态代理模式
- VueX(Vuex|VueX(Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式)
- Kotlin基础(10)-代理模式在kotlin中的使用
- 长谈的确是这个时代需要的一种模式
- 《读_Head_First_有感》_“命令模式”
- 洗洗睡了|洗洗睡了 | 休息的时候,千万注意切换你的行为模式
- 设计模式【15】--从审批流中学习责任链模式