"老板,来一个手抓饼, 加个培根, 加个鸡蛋,多少钱?" |
1.手抓饼 核心角色 |
2.配菜(鸡蛋/培根/香肠...) 装饰器角色 |
那么咱们有多少种手抓饼呢?
原味手抓饼/加鸡蛋手抓饼/加鸡蛋加培根手抓饼/加鸡蛋加烤肠手抓饼/加鸡蛋加培根加烤肠手抓饼手抓饼/.......
很显然,这就是数学中的组合,最终的个数跟咱们到底有多少种配菜有关系
|
在现实世界里面,你会很天然的说 "老板,来一个手抓饼, 加个培根, 加个鸡蛋,多少钱?""
|
那么为何在程序世界里面,你却极可能说"老板,给我来一个加了鸡蛋加了培根的那种手抓饼" 呢? |
package decorator; /** * Created by noteless on 2018/9/6. * Description:手抓饼接口 描述抽象的手抓饼 */ public interface HandPancake { /** * 提供手抓饼 */ String offerHandPancake(); /**计算手抓饼的价格 * @return */ Integer calcCost(); } package decorator; /** * Created by noteless on 2018/9/6. * Description: Noteless 家的手抓饼 */ public class NotelessHandPancake implements HandPancake { /** * 提供noteless 家的手抓饼一份 */ @Override public String offerHandPancake() { return " noteless 家的手抓饼"; } /**计算 noteless 家 一份手抓饼的价格 * @return */ @Override public Integer calcCost() { return 3; } }
package decorator; /** * Created by noteless on 2018/9/6. * Description:装饰器类实现了手抓饼接口,具备了手抓饼的类型 */ public abstract class Decorator implements HandPancake{ private HandPancake handPancake; Decorator(HandPancake handPancake){ this.handPancake = handPancake; } /**提供手抓饼 * @return */ @Override public String offerHandPancake() { return handPancake.offerHandPancake(); } /**提供手抓饼的价格 * @return */ @Override public Integer calcCost() { return handPancake.calcCost(); } }
package decorator; /** * Created by noteless on 2018/9/6. * Description:培根 */ public class Bacon extends Decorator { Bacon(HandPancake handPancake){ super(handPancake); } @Override public String offerHandPancake() { return super.offerHandPancake()+" 加培根"; } @Override public Integer calcCost() { return super.calcCost()+4; } } package decorator; /** * Created by noteless on 2018/9/6. * Description:鸡蛋 */ public class Egg extends Decorator { Egg(HandPancake handPancake){ super(handPancake); } @Override public String offerHandPancake() { return super.offerHandPancake()+"加鸡蛋"; } @Override public Integer calcCost() { return super.calcCost()+2; } } package decorator; /** * Created by noteless on 2018/9/6. * Description:烤肠 */ public class Sausage extends Decorator { Sausage(HandPancake handPancake){ super(handPancake); } @Override public String offerHandPancake() { return super.offerHandPancake()+" 加香肠"; } @Override public Integer calcCost() { return super.calcCost()+3; } } package decorator; /** * Created by noteless on 2018/9/6. * Description:青菜 */ public class Vegetable extends Decorator { Vegetable(HandPancake handPancake){ super(handPancake); } @Override public String offerHandPancake() { return super.offerHandPancake()+" 加青菜"; } @Override public Integer calcCost() { return super.calcCost()+1; } }
package decorator; /** * Created by noteless on 2018/9/6. * Description:顾客具备名字,而后购买手抓饼 */ public class Customer { private String name; Customer(String name){ this.name = name; } public void buy(HandPancake handPancake){ System.out.println(name+"购买了 : "+handPancake.offerHandPancake()+ " 一份, 花了 : "+handPancake.calcCost()+"块钱~"); System.out.println(); } }
package decorator; /** * Created by noteless on 2018/9/6. * Description: * 手抓饼3块 * Sausage 烤肠 3块 * Bacon 培根 4块 * Egg 鸡蛋2块 * Vegetable 青菜 1块 */ public class Test { public static void main(String ...strings){ //有一个顾客张三,他想吃手抓饼了,来了一个原味的 Customer customerA = new Customer("张三"); customerA.buy(new NotelessHandPancake()); //有一个顾客李四,他想吃手抓饼了,他加了一根烤肠 Customer customerB = new Customer("李四"); customerB.buy(new Sausage(new NotelessHandPancake())); //有一个顾客王五,他想吃手抓饼了,他加了一根烤肠 又加了培根 Customer customerC = new Customer("王五"); customerC.buy(new Bacon(new Sausage(new NotelessHandPancake()))); //有一个顾客王五的兄弟,他想吃手抓饼了,他加了培根 又加了烤肠 Customer customerC1 = new Customer("王五的兄弟"); customerC1.buy(new Sausage(new Bacon(new NotelessHandPancake()))); //有一个顾客赵六,他想吃手抓饼了,他加了一根烤肠 又加了2份培根 Customer customerD = new Customer("赵六"); customerD.buy(new Bacon(new Bacon(new Sausage(new NotelessHandPancake()))));
//有一个顾客 王二麻子,他想吃手抓饼了,特别喜欢吃青菜 来了三分青菜 Customer customerE = new Customer("王二麻子"); customerE.buy(new Vegetable(new Vegetable(new Vegetable(new NotelessHandPancake()))));
//有一个顾客 有钱人 王大富 来了一个全套的手抓饼 Customer customerF = new Customer("王大富"); customerF.buy(new Egg(new Vegetable(new Bacon(new Sausage(new NotelessHandPancake()))))); } }
上面的代码仍是比较清晰的,若是你没办法仔细看进去的话,咱们换一种思惟方式来思考手抓饼的装饰器模式
你能够这么理解:
你过去手抓饼的摊位那边,你说老板来一个手抓饼,加培根,加鸡蛋
摊主那边是这样子的:
老板负责直接作手抓饼
旁边站着漂亮的老板娘,手里拿着手抓饼的袋子,负责帮你装袋,你总不能直接用手拿饼,对吧
接下来咱们说下过程:
老板立刻就开始作手抓饼了,作好了以后,老板把手抓饼交给了旁边站着的老板娘
老板娘在给装袋而且交给你以前
把鸡蛋和培根放到了你的手抓饼里面
而后又放到了包装袋子里面
接着递给了你
你说究竟是老板娘手里包装好的手抓饼是手抓饼 仍是老板作好的热气腾腾的是手抓饼呢?
其实,老板作好的热气腾腾的手抓饼,正是咱们上面提供出来的具体的手抓饼
老板娘手里拿着的手抓饼包装袋来包装手抓饼,也是手抓饼,只不过是包装了下,这个就是装饰器的概念
因此装饰器模式还有一个名字 包装器模式(Wrapper)
|
根本: 是你还有你 |
动态的给一个对象添加额外的职责,简单说,动态的扩展职责 就增长功能来讲,装饰器模式比生成子类要更加灵活 因此装饰器模式主要解决继承子类爆炸增加的问题 |
Component | 抽象构建 | 装饰器模式中必然有一个最基本最原始的-> 接口/抽象类 来充当抽象构建 |
抽象的手抓饼 HandPancake |
ConcreteComponent | 具体构建 |
是抽象构建的一个具体实现
你要装饰的就是它
|
具体某家店铺生产的手抓饼 NotelessHandPancake |
Decorator | 装饰抽象类 | 通常是一个抽象类 实现抽象构建 而且必然有一个private变量指向Component 抽象构建 |
配菜抽象类(装饰器) Decorator |
ConcreteDecorator | 具体的装饰类 | 必需要有具体的装饰角色 不然装饰模式就毫无心义了 |
具体的配菜(具体的装饰) Bacon Egg Vegetable Sausage |
仔细体味下<是你 还有你>
Decorator 是Component 还有Component
|
类应该对扩展开放,对修改关闭 |
所谓修改就是指继承,一旦继承,那么将会对部分源代码具备修改的能力,好比覆盖方法,因此你尽可能不要作这件事情 扩展就是指的组合,组合不会改变任何已有代码,动态得扩展功能 |
装饰器模式虽然从数量级上减小了类的数量,可是为了要装饰,仍旧会增长不少的小类 这些具体的装饰类的逻辑将不会很是的清晰,不够直观,容易使人迷惑 |
装饰器模式虽然减小了类的爆炸,可是在使用的时候,你就可能须要更多的对象来表示继承关系中的一个对象 |
多层的装饰是比较复杂,好比查找问题时,被层层嵌套,不容易发现问题所在 |
当你想要给一个类增长功能,然而,却并不想修改原来类的代码时,能够考虑装饰器模式 若是你想要动态的给一个类增长功能,而且这个功能你还但愿能够动态的撤销,就好像直接拿掉了一层装饰物 |
设计模式是做为解决问题或者设计类层级结构时的一种思惟的存在,而不是公式同样的存在!
|