前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >装饰器模式实际运用_个人工作总结总结的格式

装饰器模式实际运用_个人工作总结总结的格式

作者头像
Java架构师必看
发布2022-08-15 17:08:42
3780
发布2022-08-15 17:08:42
举报
文章被收录于专栏:Java架构师必看Java架构师必看

大家好,我是架构君,一个会写代码吟诗的架构师。今天说一说装饰器模式实际运用_个人工作总结总结的格式,希望能够帮助大家进步!!!

目录

一、装饰器模式的概念及怎么用?

1.基本概念和功能

2.结构图分析

3.举例分析

二、装饰器模式的基本用法

1.接口定义:去定义具体需要实现的相关方法

2.具体对象:针对需要实现的方法做初始化操作,即基本的实现

3.装饰类:抽象类,初始化具体对象

4.其他具体装饰类实现自己特性的需求

5.实际使用

三、具体案例分析

目标:用装饰器模式动手实现一套商品价格策略的优化方案。

1.先建立订单和商品的属性类:主订单+详细订单+商品+促销类型+优惠券+红包

2.建立计算支付金额的接口类以及基本类

3.建立计算支付金额的抽象类(调用基本类)

4.优惠券计算类通过继承抽象类来实现所需要的修饰类

5.红包计算类通过继承抽象类来实现所需要的修饰类

6.通过一个工厂类来组合商品的促销类型

7.实际使用操作

参考书籍、文献和资料


一、装饰器模式的概念及怎么用?

1.基本概念和功能

装饰器模式能够实现从一个对象的外部来给对象添加功能,有非常灵活的扩展性,可以在对原来的代码毫无修改的前提下,为对象添加新功能。除此之外,装饰器模式还能够实现对象的动态组合,借此我们可以很灵活地给动态组合的对象,匹配所需要的功能

2.结构图分析

  • Component为统一接口,也是装饰类和被装饰类的基本类型。
  • ConcreteComponent为具体实现类,也是被装饰类,他本身是个具有一些功能的完整的类。
  • Decorator是装饰类,实现了Component接口的同时还在内部维护了一个ConcreteComponent的实例,并可以通过构造函数初始化。而Decorator本身,通常采用默认实现,他的存在仅仅是一个声明:我要生产出一些用于装饰的子类了。而其子类才是赋有具体装饰效果的装饰产品类。
  • ConcreteDecorator是具体的装饰产品类,每一种装饰产品都具有特定的装饰效果。可以通过构造器声明装饰哪种类型的ConcreteComponent,从而对其进行装饰。

3.举例分析

假设现在有这样一个需求,让你设计一个装修功能,用户可以动态选择不同的装修功能来装饰自己的房子。例如,水电装修、天花板以及粉刷墙等属于基本功能,而设计窗帘装饰窗户、设计吊顶装饰房顶等未必是所有用户都需要的,这些功能则需要实现动态添加。还有就是一旦有新的装修功能,我们也可以实现动态添加。

采用装饰器模式可以很好的解决以上问题。

二、装饰器模式的基本用法

基于装饰器模式实现的装修功能的代码结构简洁易读,业务逻辑也非常清晰,并且如果我们需要扩展新的装修功能,只需要新增一个继承了抽象装饰类的子类即可。

装饰器模式包括了以下几个角色:接口、具体对象、装饰类、具体装饰类

  • 接口定义了具体对象的一些实现方法;
  • 具体对象定义了一些初始化操作,比如开头设计装修功能的案例中,水电装修、天花板以及粉刷墙等都是初始化操作;
  • 装饰类则是一个抽象类,主要用来初始化具体对象的一个类;
  • 其它的具体装饰类都继承了该抽象类。

1.接口定义:去定义具体需要实现的相关方法

代码语言:javascript
复制
/**
 * 描述:定义一个基本装修接口
 *
 * @author yanfengzhang
 * @date 2020-04-19 13:32
 */
public interface IDecorator {
    /**
     * 装修方法
     */
    void decorate();
}

只听到从架构师办公室传来架构君的声音:

田家老翁住东陂,说道平生隐在兹。有谁来对上联或下联?

2.具体对象:针对需要实现的方法做初始化操作,即基本的实现

代码语言:javascript
复制
/**
 * 描述:装修基本类
 *
 * @author yanfengzhang
 * @date 2020-04-19 13:32
 */
public class Decorator implements IDecorator {
    /**
     * 基本实现方法
     */
    @Override
    public void decorate() {
        System.out.println("水电装修、天花板以及粉刷墙.");
    }
}

3.装饰类:抽象类,初始化具体对象

代码语言:javascript
复制
/**
 * 描述:基本装饰类
 *
 * @author yanfengzhang
 * @date 2020-04-19 13:34
 */
public abstract class BaseDecorator implements IDecorator {
    private IDecorator decorator;

    public BaseDecorator(IDecorator decorator) {
        this.decorator = decorator;
    }

    /**
     * 调用装饰方法
     */
    @Override
    public void decorate() {
        if (decorator != null) {
            decorator.decorate();
        }
    }
}

4.其他具体装饰类实现自己特性的需求

如果我们想要在基础类上添加新的装修功能,只需要基于抽象类 BaseDecorator 去实现继承类,通过构造函数调用父类,以及重写装修方法实现装修窗帘的功能即可。

代码语言:javascript
复制
/**
 * 描述:窗帘装饰类
 *
 * @author yanfengzhang
 * @date 2020-04-19 13:35
 */
public class CurtainDecorator extends BaseDecorator {
    public CurtainDecorator(IDecorator decorator) {
        super(decorator);
    }

    /**
     * 窗帘具体装饰方法
     */
    @Override
    public void decorate() {
        System.out.println("窗帘装饰。。。");
        super.decorate();
    }
}

5.实际使用

代码语言:javascript
复制
/**
 * 描述:具体使用测试
 *
 * @author yanfengzhang
 * @date 2020-04-19 13:36
 */
public class Test {
    public static void main(String[] args) {
        IDecorator decorator = new Decorator();
        IDecorator curtainDecorator = new CurtainDecorator(decorator);
        curtainDecorator.decorate();
    }
}

三、具体案例分析

每逢双十一,为了加大商城的优惠力度,开发往往要设计红包 + 限时折扣或红包 + 抵扣券等组合来实现多重优惠。而在平时,由于某些特殊原因,商家还会赠送特殊抵扣券给购买用户,而特殊抵扣券 + 各种优惠又是另一种组合方式。

要实现以上这类组合优惠的功能,刚刚介绍的装饰器模式就很适合用在这里,其相互独立、自由组合以及方便动态扩展功能的特性,可以很好地解决这类需求。

目标:用装饰器模式动手实现一套商品价格策略的优化方案。

1.先建立订单和商品的属性类:主订单+详细订单+商品+促销类型+优惠券+红包

订单和商品的属性类只建立了几个关键字段,主订单包含若干详细订单,详细订单中记录了商品信息,商品信息中包含了促销类型信息,一个商品可以包含多个促销类型(只讨论单个促销和组合促销)

  • 主订单
代码语言:javascript
复制
import java.math.BigDecimal;
import java.util.List;

/**
 * 描述:主订单
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:01
 */
@Data
public class Order {
    /**
     * 订单ID
     */
    private int id;
    /**
     * 订单号
     */
    private String orderNo;
    /**
     * 总支付金额
     */
    private BigDecimal totalPayMoney;
    /**
     * 详细订单列表
     */
    private List<OrderDetail> list;
}
  • 详细订单
代码语言:javascript
复制
import java.math.BigDecimal;

/**
 * 描述:详细订单
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:06
 */
@Data
public class OrderDetail {
    /**
     * 详细订单ID
     */
    private int id;
    /**
     * 主订单ID
     */
    private int orderId;
    /**
     * 商品详情
     */
    private Merchandise merchandise;
    /**
     * 支付单价
     */
    private BigDecimal payMoney;
}
  • 具体商品
代码语言:javascript
复制
import java.math.BigDecimal;
import java.util.Map;

/**
 * 描述:具体商品
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:09
 */
@Data
public class Merchandise {
    /**
     * 商品SKU
     */
    private String sku;
    /**
     * 商品名称
     */
    private String name;
    /**
     * 商品单价
     */
    private BigDecimal price;
    /**
     * 支持促销类型
     */
    private Map<PromotionType, SupportPromotions> supportPromotions;
}
  • 促销类型
代码语言:javascript
复制
/**
 * 描述:促销类型
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:16
 */
public enum PromotionType {
    /**
     * 优惠卷
     */
    COUPON,
    /**
     * 红包
     */
    REDPACKED;
}
  • 优惠券
代码语言:javascript
复制
import java.math.BigDecimal;

/**
 * 描述:优惠券
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:13
 */
@Data
public class UserCoupon {
    /**
     * 优惠券ID
     */
    private int id;
    /**
     * 领取优惠券用户ID
     */
    private int userId;
    /**
     * 商品SKU
     */
    private String sku;
    /**
     * 优惠金额
     */
    private BigDecimal coupon;
}
  • 红包
代码语言:javascript
复制
import java.math.BigDecimal;

/**
 * 描述:红包
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:14
 */
@Data
public class UserRedPacket {
    /**
     * 红包ID
     */
    private int id;
    /**
     * 领取用户ID
     */
    private int userId;
    /**
     * 商品SKU
     */
    private String sku;
    /**
     * 领取红包金额
     */
    private BigDecimal redPacket;
}
  • 促销类型
代码语言:javascript
复制
/**
 * 描述:促销类型
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:16
 */
@Data
public class SupportPromotions implements Cloneable {
    /**
     * 该商品促销的ID
     */
    private int id;
    /**
     * 促销类型 1\优惠券 2\红包
     */
    private PromotionType promotionType;
    /**
     * 优先级
     */
    private int priority;
    /**
     * 用户领取该商品的优惠券
     */
    private UserCoupon userCoupon;
    /**
     * 用户领取该商品的红包
     */
    private UserRedPacket userRedPacket;

    /**
     * 重写clone方法
     */
    @Override
    public SupportPromotions clone() {
        SupportPromotions supportPromotions = null;
        try {
            supportPromotions = (SupportPromotions) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return supportPromotions;
    }
}

2.建立计算支付金额的接口类以及基本类

  • 基本接口定义
代码语言:javascript
复制
/**
 * 描述:计算支付金额接口类
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:09
 */

public interface IBaseCount {
    /**
     * 功能描述:计算支付金额
     * @author yanfengzhang
     * @date 2020-04-19 14:40
     * @param orderDetail
     * @return BigDecimal
    */
    BigDecimal countPayMoney(OrderDetail orderDetail);
}
  • 基本实现类
代码语言:javascript
复制
/**
 * 描述:支付基本类
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:41
 */
public class BaseCount implements IBaseCount {
    @Override
    public BigDecimal countPayMoney(OrderDetail orderDetail) {
        orderDetail.setPayMoney(orderDetail.getMerchandise().getPrice());
        System.out.println("商品原单价金额为:" + orderDetail.getPayMoney());
        return orderDetail.getPayMoney();
    }
}

3.建立计算支付金额的抽象类(调用基本类)

代码语言:javascript
复制
/**
 * 描述:计算支付金额的抽象类
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:48
 */
public abstract class BaseCountDecorator implements IBaseCount {
    private IBaseCount count;

    public BaseCountDecorator(IBaseCount count) {
        this.count = count;
    }

    @Override
    public BigDecimal countPayMoney(OrderDetail orderDetail) {
        BigDecimal payTotalMoney = new BigDecimal(0);
        if (count != null) {
            payTotalMoney = count.countPayMoney(orderDetail);
        }
        return payTotalMoney;
    }
}

4.优惠券计算类通过继承抽象类来实现所需要的修饰类

代码语言:javascript
复制
/**
 * 描述:计算使用优惠券后的金额
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:50
 */
public class CouponDecorator extends BaseCountDecorator {
    public CouponDecorator(IBaseCount count) {
        super(count);
    }

    @Override
    public BigDecimal countPayMoney(OrderDetail orderDetail) {
        BigDecimal payTotalMoney = new BigDecimal(0);
        payTotalMoney = super.countPayMoney(orderDetail);
        payTotalMoney = countCouponPayMoney(orderDetail);
        return payTotalMoney;
    }

    private BigDecimal countCouponPayMoney(OrderDetail orderDetail) {
        BigDecimal coupon = orderDetail.getMerchandise().getSupportPromotions().get(PromotionType.COUPON).getUserCoupon().getCoupon();
        System.out.println("优惠券金额:" + coupon);
        orderDetail.setPayMoney(orderDetail.getPayMoney().subtract(coupon));
        return orderDetail.getPayMoney();
    }
}

5.红包计算类通过继承抽象类来实现所需要的修饰类

代码语言:javascript
复制
/**
 * 描述:计算使用红包后的金额
 *
 * @author yanfengzhang
 * @date 2020-04-19 15:24
 */
public class RedPacketDecorator extends BaseCountDecorator {

    public RedPacketDecorator(IBaseCount count) {
        super(count);
    }

    @Override
    public BigDecimal countPayMoney(OrderDetail orderDetail) {
        BigDecimal payTotalMoney = new BigDecimal(0);
        payTotalMoney = super.countPayMoney(orderDetail);
        payTotalMoney = countCouponPayMoney(orderDetail);
        return payTotalMoney;
    }

    private BigDecimal countCouponPayMoney(OrderDetail orderDetail) {

        BigDecimal redPacket = orderDetail.getMerchandise().getSupportPromotions().get(PromotionType.REDPACKED).getUserRedPacket().getRedPacket();
        System.out.println("红包优惠金额:" + redPacket);

        orderDetail.setPayMoney(orderDetail.getPayMoney().subtract(redPacket));
        return orderDetail.getPayMoney();
    }
}

6.通过一个工厂类来组合商品的促销类型

代码语言:javascript
复制
/**
 * 描述:计算促销后的支付价格
 *
 * @author yanfengzhang
 * @date 2020-04-19 14:58
 */
public class PromotionFactory {
    public static BigDecimal getPayMoney(OrderDetail orderDetail) {
        /**获取给商品设定的促销类型*/
        Map<PromotionType, SupportPromotions> supportPromotionsList = orderDetail.getMerchandise().getSupportPromotions();

        /**初始化计算类*/
        IBaseCount baseCount = new BaseCount();
        if (supportPromotionsList != null && supportPromotionsList.size() > 0) {
            for (PromotionType promotionType : supportPromotionsList.keySet()) {
                /**遍历设置的促销类型,通过装饰器组合促销类型*/
                baseCount = protmotion(supportPromotionsList.get(promotionType), baseCount);
            }
        }
        return baseCount.countPayMoney(orderDetail);
    }

    /**
     * 组合促销类型 * @param supportPromotions * @param baseCount * @return
     */
    private static IBaseCount protmotion(SupportPromotions supportPromotions, IBaseCount baseCount) {
        if (supportPromotions.getPromotionType() == PromotionType.COUPON) {
            baseCount = new CouponDecorator(baseCount);
        } else if (supportPromotions.getPromotionType() == PromotionType.REDPACKED) {
            baseCount = new RedPacketDecorator(baseCount);
        }
        return baseCount;
    }
}

7.实际使用操作

代码语言:javascript
复制
/**
 * 描述:测试
 *
 * @author yanfengzhang
 * @date 2020-04-19 15:35
 */
public class Test {
    volatile int counter = 0;

    private static Order init(Order order) {
        Map<PromotionType, SupportPromotions> supportPromotionslist = new HashMap<PromotionType, SupportPromotions>();

        SupportPromotions supportPromotions = new SupportPromotions();
        supportPromotions.setPromotionType(PromotionType.COUPON);
        supportPromotions.setPriority(1);

        UserCoupon userCoupon = new UserCoupon();
        userCoupon.setCoupon(new BigDecimal(3));
        userCoupon.setSku("aaa1111");
        userCoupon.setUserId(11);

        supportPromotions.setUserCoupon(userCoupon);

        supportPromotionslist.put(PromotionType.COUPON, supportPromotions);
        SupportPromotions supportPromotions1 = supportPromotions.clone();

        supportPromotions1.setPromotionType(PromotionType.REDPACKED);
        supportPromotions1.setPriority(2);

        UserRedPacket userRedPacket = new UserRedPacket();
        userRedPacket.setId(1);
        userRedPacket.setRedPacket(new BigDecimal(10));
        userRedPacket.setSku("aaa1111");
        userCoupon.setUserId(11);

        supportPromotions1.setUserRedPacket(userRedPacket);
        supportPromotionslist.put(PromotionType.REDPACKED, supportPromotions1);

        Merchandise merchandise = new Merchandise();
        merchandise.setSku("aaa1111");
        merchandise.setName("苹果");
        merchandise.setPrice(new BigDecimal(20));
        merchandise.setSupportPromotions(supportPromotionslist);

        List<OrderDetail> OrderDetailList = new ArrayList<OrderDetail>();
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setId(1);
        orderDetail.setOrderId(1111);
        orderDetail.setMerchandise(merchandise);

        OrderDetailList.add(orderDetail);
        order.setList(OrderDetailList);

        return order;
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        Order order = new Order();
        init(order);

        for (OrderDetail orderDetail : order.getList()) {
            BigDecimal payMoney = PromotionFactory.getPayMoney(orderDetail);
            orderDetail.setPayMoney(payMoney);
            System.out.println("最终支付金额:" + orderDetail.getPayMoney());
        }
    }
}

实际测试输入:

代码语言:javascript
复制
商品原单价金额为:20
红包优惠金额:10
优惠券金额:3
最终支付金额:7

参考书籍、文献和资料

1.极客时间课程《Java性能调优实战》,刘超,2019.

2.https://www.cnblogs.com/jzb-blog/p/6717349.html

今天文章到此就结束了,感谢您的阅读,Java架构师必看祝您升职加薪,年年好运。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-08-142,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、装饰器模式的概念及怎么用?
    • 1.基本概念和功能
      • 2.结构图分析
        • 3.举例分析
        • 二、装饰器模式的基本用法
          • 1.接口定义:去定义具体需要实现的相关方法
            • 2.具体对象:针对需要实现的方法做初始化操作,即基本的实现
              • 3.装饰类:抽象类,初始化具体对象
                • 4.其他具体装饰类实现自己特性的需求
                  • 5.实际使用
                  • 三、具体案例分析
                    • 目标:用装饰器模式动手实现一套商品价格策略的优化方案。
                      • 1.先建立订单和商品的属性类:主订单+详细订单+商品+促销类型+优惠券+红包
                      • 2.建立计算支付金额的接口类以及基本类
                      • 3.建立计算支付金额的抽象类(调用基本类)
                      • 4.优惠券计算类通过继承抽象类来实现所需要的修饰类
                      • 5.红包计算类通过继承抽象类来实现所需要的修饰类
                      • 6.通过一个工厂类来组合商品的促销类型
                      • 7.实际使用操作
                  • 参考书籍、文献和资料
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档