专栏首页呆呆熊的技术路设计模式第三讲-装饰者模式

设计模式第三讲-装饰者模式

简介

装饰模式也算一种比较常见的设计模式,工作过程中很少刻意的去实现这种模式,因为这种模式也会带来一些问题。

比如小类太多,组织起来比较麻烦,对客户端完全可见,如果不了解各个类的功能会很乱等等

当然也有很多优点: 可以动态的给类增加一些职责,增加功能更加灵活,比起继承来说也更加具有弹性

下面我们来看看它究竟是什么样子的

场景设置

以买车业务模型为例(本人未买过车,业务场景纯属臆想)

车里面还有很多装备可以选择,根据不同的选择装饰决定最后到手的价格:

商品

价格

裸车

100000

加热座椅(可选)

4000

真皮内饰(可选)

8000

蹦迪音响(可选)

5000

第一版本实现(我们在一个类里面完成)

package car;

public class Car {

    //总价
    private int allPrice = 0;

    //裸车价格 --实际数值从数据库查询,此处略
    private int nakedPrice = 100000;

    //加热座椅
    private int heatedSeat = 4000;

    //真皮内饰
    private int dermalInteriors = 8000;

    //蹦迪音响
    private int bengdiSound = 5000;


    public Car() {
        this.allPrice += this.nakedPrice;
    }

    /**
     * 添加真皮座椅
     */
    public void addHeatedSeat() {
        this.allPrice += this.heatedSeat;
    }

    /**
     * 添加真皮内饰
     */
    public void addDermalInteriors() {
        this.allPrice += this.dermalInteriors;
    }

    /**
     * 添加蹦迪音响
     */
    public void addBengdiSound() {
        this.allPrice += this.bengdiSound;
    }

    /**
     * 获取总价
     *
     * @return
     */
    public int cost() {
        return this.allPrice;
    }

}

客户端调用:

package car;

public class Main {

    public static void main(String[] args) {

        Car car = new Car();

        car.addBengdiSound();
        System.out.println("总花费价格:" + car.cost());

    }

}

output:

花费价格105000

看起来很简洁呢,并且也很好的实现了功能

首先这是我们的场景足够的简单,所涉及的配套组件也比较少,实际中可能针对某个方法可能有很复杂的获取和计算逻辑,组件也会有很多种选择,会造成类爆炸,无法继续维护下去

如果我们使用装饰模式,会带来什么改变呢,会给我们带来什么样的体验呢

设计:

实现:

声明抽象类(被装饰者和装饰者继承此类,目的对实现方法进行规正)

package car;

public abstract class Car {

    public String name;

    public abstract String cost();
}

主角:被装饰者类-裸车

package car;

/**
 * 被装饰的类 -> 裸车
 */
public class NakeCar extends Car {

    //裸车价格 --实际数值从数据库查询,此处略
    private int nakedPrice = 100000;


    public NakeCar() {
        this.name = "裸车";
    }

    /**
     * 获取总价
     *
     * @return
     */
    public String cost() {
        return this.name + ":" + this.nakedPrice;
    }
}

具体装饰类:

加热座椅

package car;

/**
 * 装饰组件
 */
public class HeatedSeat extends Car {

    //加热座椅
    private int heatedSeat = 4000;

    //汽车对象
    private Car car;

    public HeatedSeat(Car car) {
        this.name = "加热座椅";
        this.car = car;
    }

    /**
     * 获取价格
     *
     * @return
     */
    public String cost() {
        //todo
        return this.car.cost() + "||" + this.name + ":" + this.heatedSeat;
    }

}

真皮内饰

package car;

public class DermalInteriors extends Car {

    //真皮内饰
    private int dermalInteriors = 8000;

    //汽车对象
    private Car car;

    public DermalInteriors(Car car) {
        this.name = "真皮内饰";
        this.car = car;
    }

    /**
     * 获取价格
     *
     * @return
     */
    public String cost() {
        //todo
        return this.car.cost() + "||" + this.name + ":" + this.dermalInteriors;
    }

}

蹦迪音响

package car;

public class BengdiSound extends Car {

    //蹦迪音响
    private int bengdiSound = 5000;

    //汽车对象
    private Car car;

    public BengdiSound(Car car) {
        this.name = "蹦迪音响";
        this.car = car;
    }

    /**
     * 获取价格
     *
     * @return
     */
    public String cost() {
        //todo
        return this.car.cost() + "||" + this.name + ":" + this.bengdiSound;
    }
}

客户端调用:

package car;

public class Main {

    public static void main(String[] args) {

        NakeCar car = new NakeCar();

        HeatedSeat heatedSeat = new HeatedSeat(car);
        BengdiSound bengdiSound = new BengdiSound(heatedSeat);
        System.out.println("总花费价格:" + bengdiSound.cost());
    }
}

output:

总花费价格:裸车:100000||加热座椅:4000||蹦迪音响:5000

总结

  • 装饰模式的优点: 可以为已有的功能(被装饰对象)动态的添加功能,简化原有类。在我们的例子中, 裸车是主类,相当于业务中的核心,而一些动态的组件可以根据实际情况使用,也就相当于我们业务线中的附属拓展功能。 主逻辑和拓展逻辑的区分会使我们的代码更具拓展性。
  • 装饰模式的缺点: 我们可以看到装饰模式的引入会增多类的数量,以及客户端的使用会有复杂度上升。装饰模式的类依赖特定的类型,需要严格遵守规约(抽象类的约束)

本文分享自微信公众号 - 呆呆熊的技术路(gh_93f28f51010a),作者:近视小猴子

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 设计模式第七讲-责任链模式

    责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系

    用户2825413
  • 计数器、滑动窗口、漏桶、令牌算法比较和伪代码实现

    计数器是限流里最简单的,简单来说,比如 我限制1分钟内 请求数最多为60个! 当此刻 2018-02-27 16:23:00 到 2018-02-27 16:2...

    用户2825413
  • 一分钟 - ngx_http_rewrite_module模块

    用户2825413
  • python 使用列表和字典存储信息

    py3study
  • 快速学习-Spring Data JPA的内部原理剖析

    在客户的案例中,我们发现在自定义的CustomerDao中,并没有提供任何方法就可以使用其中的很多方法,那么这些方法究竟是怎么来的呢?答案很简单,对于我们自定义...

    cwl_java
  • 【设计模式之责任链模式】

    1、定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。

    用户5640963
  • [Cocos Creator] 围绕物体旋转

    在游戏开发过程中,可能会有让一个物体围绕另一个物体旋转的需求,就比如月球围绕着地球旋转,同时地球也在围绕着太阳旋转。

    陈皮皮
  • 如何做到复学防疫两不误?“高校防疫指南”专家组明天在线划重点

    ? 眼下,全国各大高校马上要返校开学了。 面对从全国各地甚至海外返校的师生, 学校该如何做到复学防疫两不误? 高校返校复学, 涉及到教学、教务、生活等多个维度...

    鹅老师
  • 详解javascript中this的工作原理

    在 JavaScript 中 this 常常指向方法调用的对象,但有些时候并不是这样的,本文将详细解读在不同的情况下 this 的指向。

    用户6167509
  • Java 实践

    Mirror王宇阳

扫码关注云+社区

领取腾讯云代金券