乐趣区

关于java:轻松搞懂设计模式看完起飞的装饰者模式

我是 <font color=#2941c0>「kangarooking(袋鼠帝)」</font>,不是弟弟的弟。一个互联网小蜗「gua」牛,陪大家一起一步一步往上爬,总有一天有属于咱们的天。关注 me,每天提高亿点点 ❗ ❗ ❗

前言

上期责任链模式文章外面给大家提到的学习设计模式的心得,原本是要在这期写给铁子们的,然而我思前想后,感觉机会尚未成熟。我筹备在「轻松搞懂设计模式」系列完结后的总结性文章外面通知大伙。

絮絮叨叨

不晓得大家有没有这样的感觉,就是设计模式如同大多用在框架外面,本人的业务代码外面根本没有应用过设计模式。其实很多业务场景都能够应用设计模式来解决 然而可能因为负责人对设计模式的理解还比拟通俗,也可能因为我的项目赶进度等起因而没有应用。那么明天这篇文章就厉害了 0.0, 看完间接能够将装璜者模式引入本人的我的项目,让领导对你另眼相看,升职加薪,赢取白富美就不远了。想想都有点美滋滋呢 😍,腾飞腾飞~✈️

概念

装璜器(Decorator)模式的定义:指在不扭转现有对象构造的状况下,动静地给该对象减少一些职责(即减少其额定性能)的模式,它属于对象结构型模式。

长处

  • 装璜器是继承的无力补充,比继承灵便,在不扭转原有对象的状况下,动静的给一个对象扩大性能,即插即用
  • 通过应用不必装璜类及这些装璜类的排列组合,能够实现不同成果
  • 装璜器模式齐全恪守开闭准则

毛病

  • 装璜器模式会减少许多子类,适度应用会减少程序得复杂性。

为什么不应用继承来搞?

通常状况下,扩大一个类的性能会应用继承形式来实现。但继承具备动态特色,耦合度高,并且随着扩大性能的增多,子类会很收缩。

装璜者模式的指标

应用组合关系来创立一个包装对象(即装璜对象)来包裹实在对象,并在放弃实在对象的类构造不变的前提下,为其提供额定的性能。

装璜者模式应用场景

  • 当须要给一个现有类增加附加职责,而又不能采纳生成子类的办法进行裁减时。例如,该类被暗藏或者该类是终极类或者采纳继承形式会产生大量的子类。
  • 当须要通过对现有的一组基本功能进行排列组合而产生十分多的性能时,采纳继承关系很难实现,而采纳装璜器模式却很好实现。
  • 当对象的性能要求能够动静地增加,也能够再动静地撤销时。

定义角色
指标对象:被装璜的原始对象;
装璜者形象:形象的装璜者;
具体装璜者:装璜者形象的具体实现。

代码示例

业务场景:公司订单有多种优惠形式,优惠券,vip 优惠,积分流动,红包 and so on… 这个时候咱们就能够思考应用装璜者模式来对原订单对象进行装璜,通过装璜让一般订单成为一个蕴含多种 / 单个优惠活动的订单。<br/> 代码地址:https://gitee.com/kangarookin… <br/> 留神:本示例只是简略的帮忙了解设计模式的代码实现和理论我的项目有间隔。理论我的项目实现订单优惠可参考:https://blog.csdn.net/ceoaxv5…

订单类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
    private Double price;
    private Integer orderId;
    private String orderNo;
    private Double pay;
    private List<Integer> promotionTypeList;
}

流动的枚举类,用于记录流动类型

/**
 * 流动枚举
 */
public enum PromotionType {COUPON(1),
    VIP(2);
    private int type;

    PromotionType(final int type){this.type = type;}

    public int getType() {return type;}

    public void setType(int type) {this.type = type;}
}

装璜订单的装璜者接口

/**
 * 订单装璜者接口
 */
public interface OrderDecorator {
    // 形象装璜办法
    Order decorator(Order order);
}

订单装璜者实现类 – 优惠券订单装璜者

/**
 * 优惠券装璜者
 */
public class CouponOrderDecorator implements OrderDecorator {
    @Override
    public Order decorator(Order order) {System.out.println("优惠券减去 3 元");
        order.setPay(order.getPrice() - 3);
        order.setPrice(order.getPrice() - 3);
        System.out.println("实付:" + order.getPay());
        return order;
    }
}

订单装璜者实现类 –VIP 订单装璜者

/**
 * vip 装璜者
 */
public class VipOrderDecorator implements OrderDecorator {
    @Override
    public Order decorator(Order order) {System.out.println("vip 减去 1 元");
        order.setPay(order.getPrice() - 1);
        order.setPrice(order.getPrice() - 1);
        System.out.println("实付:" + order.getPay());
        return order;
    }
}

上面就看看具体怎么应用吧

public class DecoratorClient {public static void main(String[] args) {
        // 创立一个原始订单
        Order order = new Order(10d, 1, "0001", 10d, null);
        // 创立装璜者子类对象
        OrderDecorator vipOrderDecorator = new VipOrderDecorator();
        OrderDecorator couponOrderDecorator = new CouponOrderDecorator();
        // 应用 vip 和优惠券包装原订单对象,使其领有 vip 和优惠券的优惠。// 在某些状况下(依据具体需要来实现)还能够依据包装的程序不同而取得不同的后果。Order vipCouponOrder = couponOrderDecorator.decorator(vipOrderDecorator.decorator(order));
    }
}

装璜者模式在开源代码中的应用

java.io 中的利用

装璜者模式在 Java 语言中的最驰名的利用莫过于 Java I/O 规范库的设计了。例如,InputStream 的子类 FilterInputStreamOutputStream 的子类 FilterOutputStreamReader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriterFilterWriter 以及 PrintWriter 等,它们都是形象装璜类。

上面看一个例子,BufferedReader实现装璜者的形式是继承 Reader 类,而后将 Reader 类定义为本人的成员变量。这里的 Reader 即是装璜者形象,又是指标对象的形象,BufferedReader是具体装璜者,又是指标对象。

FilterReader的形式和 BufferedReader 的实现形式一样

为什么 BufferedReader 没有应用下面示例代码的实现形式呢?

这其实就是陈词滥调的 – 设计模式是一种思维,实现形式有多种多样。BufferedReader类外部没有相似示例代码中的 decorator() 办法,所以它通过将指标对象定义为成员变量的形式来引入指标对象(而不是将指标对象定义形参的形式), 从而达到将其余 Reader 实现类的性能装璜到本身的目标。

这里只是简略的阐明了这种实现装璜者的用法,具体的外部源码大家能够本人去看一下,办法的外部最终还是调用了 in.xxx 办法。

public static void main(String[] args) throws IOException {Reader file = new FileReader("xxx 门路");
        //FilterReader 中应用 FileReader 进行装璜
        FilterReader filterReader = new PushbackReader(file);
        //BufferedReader 中应用 FilterReader 进行装璜
        Reader bufferedReader = new BufferedReader(filterReader);
        // 最终调用 BufferedReader 的 read,close 办法
        // 就取得了 FilterReader 以及 FileReader 的性能
        bufferedReader.read();
        bufferedReader.close();}

shenyu 网关中的利用

shenyu上下文装璜者接口,次要用于依据不同的接入类型来组装不同的上下文信息。

shenyugrpc 上下文装璜者实现类,这种实现形式就和实例代码一样,有一个 decorator() 办法将指标对象 ShenyuContext 当做形参传入,而后在该办法内对 ShenyuContext 进行 grpc 类型的装璜。


shenyu 也是一个比拟 nice 的开源网关框架,是国人开源的新作品,有很高的学习价值和实用性。我在老东家的架构组过后就是引入了该网关,由咱们架构组保护和二开。所以对这个网关框架外部实现比拟相熟,也会常常用它来举例子。

github 地址:https://github.com/apache/inc… <br/> 官网文档地址:https://shenyu.apache.org/

总结

还是陈词滥调的设计模式是一种思维,咱们要的是把握了解思维,并将其转化为代码中的实现,利用到理论的工作中。兄弟们平时能够多拉几个开源框架的源码到本地,没事的时候就看看人家怎么写的代码,比方装璜者模式就能够全局搜寻 decorator 来查找相干代码。

微信公众号 <font color=#2941c0>「袋鼠学生的客栈」</font>,你们的三连,是我的饲料~~。点赞👍 关注❤️ 分享👥

退出移动版