前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式第三讲-装饰者模式

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

作者头像
用户2825413
发布2019-07-16 11:05:22
2990
发布2019-07-16 11:05:22
举报

简介

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

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

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

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

场景设置

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

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

商品

价格

裸车

100000

加热座椅(可选)

4000

真皮内饰(可选)

8000

蹦迪音响(可选)

5000

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

代码语言:javascript
复制
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;
    }

}

客户端调用:

代码语言:javascript
复制
package car;

public class Main {

    public static void main(String[] args) {

        Car car = new Car();

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

    }

}

output:

代码语言:javascript
复制
花费价格105000

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

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

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

设计:

实现:

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

代码语言:javascript
复制
package car;

public abstract class Car {

    public String name;

    public abstract String cost();
}

主角:被装饰者类-裸车

代码语言:javascript
复制
package car;

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

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


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

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

具体装饰类:

加热座椅

代码语言:javascript
复制
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;
    }

}

真皮内饰

代码语言:javascript
复制
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;
    }

}

蹦迪音响

代码语言:javascript
复制
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;
    }
}

客户端调用:

代码语言:javascript
复制
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:

代码语言:javascript
复制
总花费价格:裸车:100000||加热座椅:4000||蹦迪音响:5000

总结

  • 装饰模式的优点: 可以为已有的功能(被装饰对象)动态的添加功能,简化原有类。在我们的例子中, 裸车是主类,相当于业务中的核心,而一些动态的组件可以根据实际情况使用,也就相当于我们业务线中的附属拓展功能。 主逻辑和拓展逻辑的区分会使我们的代码更具拓展性。
  • 装饰模式的缺点: 我们可以看到装饰模式的引入会增多类的数量,以及客户端的使用会有复杂度上升。装饰模式的类依赖特定的类型,需要严格遵守规约(抽象类的约束)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 呆呆熊的技术路 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 场景设置
  • 第一版本实现(我们在一个类里面完成)
  • 设计:
  • 实现:
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档