应用场景

京东、天猫双十一,情人节商品大促销,各种商品有不同的促销活动

满减:满200减50

每满减:每满100减10

打折:买两件8折,三件7折

数量减:满三件减去最低价的一件

假设现在顾客买了两件衣服先是打了8折,然后又满200减了50,促销活动多重叠加了,该如何灵活实现订单金额计算?

代码示例

PromotionAlgorithm接口,计算订单金额:

public interface PromotionAlgorithm{

Order promotionAlgorithm(Order order);

}

复制代码

实现类PromotionAlgorithm1、PromotionAlgorithm2:

public class PromotionAlgorithm1 implements PromotionAlgorithm{

@Override

public Order promotionAlgorithm(Order order){

System.out.println("打8折");

order.setPrice(order.getPrice() * 0.8);

return order;

}

}

复制代码

public class PromotionAlgorithm2 implements PromotionAlgorithm{

@Override

public Order promotionAlgorithm(Order order){

System.out.println("满200减了50");

order.setPrice(order.getPrice() - 50);

return order;

}

}

复制代码

OrderService类:

public class OrderService{

public Order getOrderPrices(Order order, String... promotion){

for (String s : promotion) {

if (s.equals("promotion-1")) {

new PromotionAlgorithm1().promotionAlgorithm(order);

} else if (s.equals("promotion-2")) {

new PromotionAlgorithm2().promotionAlgorithm(order);

}

}

return order;

}

}

复制代码

测试类:

public class Test{

public static void main(String[] args){

OrderService service = new OrderService();

Order order = new Order();

order.setPrice(1000.0);

String[] array = {"promotion-1", "promotion-2"};

Order result = service.getOrderPrices(order, array);

System.out.println("最终我花了:" + result.getPrice());

}

}

复制代码

现在思考一下,当需要对一个类的多个方法进行增强时,使用者会随意使用被增强方法时,上面的for循环还灵活吗

改进代码

定义一个接口OrderComponent:

public interface OrderComponent{

/** 促销方式 */

String getPromotion();

/** 价格 */

Double getPrice();

}

复制代码

OrderConcreteComponent类:需要进行计算的类

public class OrderConcreteComponent implements OrderComponent{

@Override

public String getPromotion(){

return "我买了三件衣服,衣服总共1000元,";

}

@Override

public Double getPrice(){

return 1000.0;

}

}

复制代码

OrderDecorator类:有一个属性,是上面的接口OrderComponent,实现了OrderComponent接口

public class OrderDecorator implements OrderComponent{

public OrderComponent component;

public OrderDecorator(OrderComponent component){

this.component = component;

}

@Override

public String getPromotion(){

return this.component.getPromotion();

}

@Override

public Double getPrice(){

return this.component.getPrice();

}

}

复制代码

OrderDecoratorA类:打折类

public class OrderDecoratorA extends OrderDecorator{

public OrderDecoratorA(OrderComponent component){

super(component);

}

@Override

public String getPromotion(){

return this.component.getPromotion() + "衣服打了8折,";

}

@Override

public Double getPrice(){

return this.component.getPrice() * 0.8;

}

}

复制代码

OrderDecoratorB类:满减类

public class OrderDecoratorB extends OrderDecorator{

public OrderDecoratorB(OrderComponent component){

super(component);

}

@Override

public String getPromotion(){

return this.component.getPromotion() + "又满200减了50。";

}

@Override

public Double getPrice(){

return this.component.getPrice() - 50;

}

}

复制代码

测试类:

public class Test{

public static void main(String[] args){

OrderComponent component = new OrderConcreteComponent();

OrderComponent c = new OrderDecorator(component);

OrderComponent d = new OrderDecoratorA(c);

OrderComponent e = new OrderDecoratorB(d);

System.out.println(e.getPromotion());

System.out.println("最终我花了:" + e.getPrice());

}

}

复制代码

上面的改进代码,就是装饰者模式的基本运用

装饰者模式

定义

以装饰的方式,动态地将责任附加到对象上,同时又不改变其结构

意图

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰者模式相比生成子类更为灵活

主要解决问题

一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀

何时使用

在不想增加很多子类的情况下扩展类

优缺点

优点:

不改变具体类代码,动态叠加增强行为功能

若要扩展功能,装饰者提供了比继承更有弹性的替代方案

装饰类和被装饰类可以独立发展,不会相互耦合

缺点:

多层装饰比较复杂

类图:

涉及到的角色:

抽象构建(Component)角色:给出一个抽象接口,来规范准备接收附加责任的对象

具体构建(ConcreteComponent)角色:定义一个将要接收附加责任的类,即被装饰者

装饰(Decorator)角色:持有一个构建(Component)对象的实例,并定义一个与抽象接口一致的接口

具体装饰(ConcreteDecorator)角色:即上图中的DecoratorA、DecoratorB,负责给构建对象贴上附加的责任,即具体的功能增强行为在这个角色里面

Component类:

public interface Component{

void sampleOperation();

}

复制代码

ConcreteComponent类:

public class ConcreteComponent implements Component{

@Override

public void sampleOperation(){

//do something

}

}

复制代码

Decorator类:

public class Decorator implements Component{

private Component component;

public Decorator(Component component){

this.component = component;

}

@Override

public void sampleOperation(){

this.component.sampleOperation();

}

}

复制代码

ConcreteDecorator类:

public class ConcreteDecorator extends Decorator{

public ConcreteDecorator(Component component){

super(component);

}

@Override

public void sampleOperation(){

super.sampleOperation();

}

}

复制代码

装饰者模式常常也被称为包裹模式,就是因为每一个具体的装饰类都将下一个具体装饰类或者具体构建类包裹起来

假设有2个具体装饰类Decorator1、Decorator2,还有一个具体构建类ConcreteComponent:

是的没错,就是像套娃一样,一层包裹一层

孙悟空的七十二变

大家都知道,孙悟空有七十二般变化,每一种变化都会给他带来一种附加的本领,变成鱼可以在水中游,变成鸟可以在空中飞,但是无论怎么样的变化,在二郎神眼中,还是一只猴子

齐天大圣类:拥有七十二般变化

public interface MonkeyKing{

/** 七十二变 */

String change();

}

复制代码

大圣本尊类:

public class ConcreteMonkey implements MonkeyKing{

@Override

public String change(){

return "我是齐天大圣本尊!";

}

}

复制代码

大圣化身类:

public class DecoratorMonkeyChange implements MonkeyKing{

public MonkeyKing king;

public DecoratorMonkeyChange(MonkeyKing king){

this.king = king;

}

@Override

public String change(){

return this.king.change();

}

}

复制代码

大圣具体化身类:

public class DecoratorMonkeyChange1 extends DecoratorMonkeyChange{

public DecoratorMonkeyChange1(MonkeyKing king){

super(king);

}

@Override

public String change(){

return this.king.change() + "变成了鱼!";

}

}

复制代码

public class DecoratorMonkeyChange2 extends DecoratorMonkeyChange{

public DecoratorMonkeyChange2(MonkeyKing king){

super(king);

}

@Override

public String change(){

return this.king.change() + "变成了鸟!";

}

}

复制代码

测试类:

public class TestMonkey{

public static void main(String[] args){

MonkeyKing king = new ConcreteMonkey();

MonkeyKing a = new DecoratorMonkeyChange(king);

MonkeyKing b = new DecoratorMonkeyChange1(a);

MonkeyKing c = new DecoratorMonkeyChange2(b);

System.out.println(c.change());

}

}

复制代码

类图:

java与模式孙悟空_由孙悟空的七十二变看Java设计模式:装饰者模式相关推荐

  1. java设计模式---装饰器模式

    装饰者模式 动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 具体被装饰者和抽象装饰类都继承于抽象被装饰者类,继承的是类型,而不是行为.行为来自装饰者和基础组件,或与其他 ...

  2. 设计模式装饰者模式_装饰者模式如何拯救了我的一天

    设计模式装饰者模式 在工作中,我正在处理庞大的Java代码库,该代码库是由许多不同的开发人员在15年的时间里开发的. 并不是所有的事情都由书来完成,但是同时我通常无法重构遇到的每一个奇怪的事物. 尽管 ...

  3. 设计模式 装饰者模式 带你重回传奇世界

    今天继续设计模式之旅,给大家带来装饰者模式,国际惯例,先看定义. 装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上. 先简单描述下装饰者模式发挥作用的地方,当我 ...

  4. 设计模式——装饰者模式

    本文是阅读 Head First 设计模式--装饰者模式的总结. 这本书的教学模式很不错,个人很喜欢,由实际的案例由浅入深,循序渐进的让你明白良好的设计是多么的优雅迷人(回头看看自己的代码,WTF!) ...

  5. 23种设计模式——装饰者模式

    文章目录 23种设计模式--装饰者模式 1.装饰者模式概述 2.装饰者模式的结构 3.装饰者模式的实现 4.装饰者模式的应用场景 23种设计模式--装饰者模式 1.装饰者模式概述 背景 有些人为了早上 ...

  6. 读书笔记---Head First 设计模式--- 装饰者模式

    读书笔记-Head First 设计模式- 装饰者模式 装饰者模式(Decorator Pattern) 装饰者模式--动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. ...

  7. Go 设计模式 - 装饰器模式

    装饰模式使用对象组合的方式动态改变或增加对象行为.Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式.使用匿名组合,在装饰器中不必显式定义转调原对象方法. 设计模式 装饰器模式 装饰器模式主要 ...

  8. 10. 设计模式-装饰者模式

    文章目录 设计模式-装饰者模式 1. 案例引出装饰者模式 2. 装饰者模式 2.1 装饰者模式定义 2.2 装饰者模式原理 2.3 装饰者模式解决星巴克咖啡订单问题 2.4 代码实现 抽象类Drink ...

  9. 7. 设计模式 装饰者模式 带你重回传奇世界

    今天继续设计模式之旅,给大家带来装饰者模式,国际惯例,先看定义. 装饰者模式:若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上. 先简单描述下装饰者模式发挥作用的地方,当我 ...

  10. 设计模式 装饰者模式

    转自:http://blog.csdn.net/lmj623565791/article/details/24269409 今天继续设计模式之旅,给大家带来装饰者模式,国际惯例,先看定义. 装饰者模式 ...

最新文章

  1. Tarjan求割点桥
  2. HDOJ2020 ( 绝对值排序 ) 【水题】
  3. S3C6410设备时钟源选择、启动方式选择和内存映射
  4. jsp中c:forEach的应用
  5. 前端学习(3171):react-hello-react之reduce
  6. 计算与推断思维 十二、为什么均值重要
  7. 有哪些优秀好用的数据采集软件?这3款你都用过吗?
  8. 西门子plc选型分析
  9. python手机版做小游戏代码大全-用Python设计一个经典小游戏
  10. gsp计算机管理制度,GSP飞检项目——质量体系文件
  11. 用Excel 随机抽取不重复n行数据
  12. 企业微信机器人消息发送(文本、图片、文件)
  13. 扒一扒那些叫欧拉的定理们(五)——平面几何欧拉定理的证明
  14. 我喜欢计算机作文450字,我喜欢的一种游戏作文450字(精选8篇)
  15. 邮件服务器收件人数量限制,qq邮箱群发邮件技巧
  16. 12306 抢票助手 Java
  17. 适合程序员编程的笔记本电脑如何选择?
  18. Linux服务器cpu性能模式,linux cpu开启性能模式
  19. SMIL彩信MMS技术学习
  20. k8s与日志--journalbeat源码解读 1

热门文章

  1. 刘韧马杰花总:诗歌小说电影游戏都是元宇宙
  2. MVC 音乐商店 第1部分: 概述和文件- 新建项目
  3. QT制作软件---窗口跟随鼠标进行移动
  4. 关机状态下启动微型计算机叫做,湖南省计算机等级考试题库
  5. 计算机同S7-300PLC通讯,S7-300PLC主站之间的PROFIBUS-DP通讯详解
  6. s盒c语言算法,AES加密算法中的S盒及其C语言实现
  7. 使用WebServiceStudio测试WebService接口
  8. 设置周一,判断周一 JS
  9. NOIP2016模拟 星际争霸(二分)
  10. Android 输入法挤压屏幕解决方案