装饰者模式

栏目: 后端 · 发布时间: 5年前

内容简介:首先需要明确一点:装饰者模式利用了通过

装饰者模式

装饰者模式 动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

思维模式

首先需要明确一点:装饰者模式利用了 “组合” 的思想,避免了“继承”的滥用。

通过 动态地组合对象 ,可以写新的代码添加新功能,而无需修改现有代码。

这就好比拼装一个机器人。

我们有各种各样的零部件:

  1. 躯干
  2. 类人的胳膊
  3. 带有钳子的胳膊
  4. 类人的腿
  5. 带轮子的腿
  6. 带履带的腿
  7. ……

简单粗暴的实现

想要设计各式各样的机器人,当然我们可以选择,设计一个 Robot 超类,然后让子类继承这个超类。

这样,我们可以得到:

  1. 躯干+人的胳膊+履带腿
  2. 躯干+钳子胳膊+轮子腿
  3. 躯干+4个人的胳膊+履带腿
  4. ……

根据排列组合的原理,如果我们需要, Robot 的子类可以有无限多个。

假如我们从 Robot 父类处继承了一个 cost() 方法,这个方法根据该子类的 component(组件) 个数和数量来计算成本(cost),那么我们的 cost() 方法可以说要重写无数次——因为每一个子类的情况都是不一样的。

“装饰者模式”的实现

我们可以先为每一个零部件(component)确定成本,然后根据需要,动态地 组装(组合) 一个机器人。然后将所有的成本加起来。如此一来,不仅可以得到一个符合我们需求的 机器人对象 ,更能很方便地计算cost。

  1. 躯干 $100
  2. 类人的胳膊 $40
  3. 带有钳子的胳膊 $50
  4. 类人的腿 $70
  5. 带轮子的腿 $70
  6. 带履带的腿 $50
  7. ……

组合一个有 躯干+类人的胳膊+带履带的腿 的机器人的 cost 也就是:

100 + 40 + 50 = $190;

实现 组合

所谓 组合 ,也就是 我中有你

如图所示:

装饰者模式

通过保有各个对象的引用,即可实现 “组合”

对于这样一个组合来的Robot对象,我们不妨称其为:“robotTom”。

想要求得总成本,可以直接调用 robotTom.cost();

这是怎样实现的呢?

如图所示:

装饰者模式

用公式来表示就是:

[robotTom].cost() 
= [arm + body].cost() + leg.cost() 
= [body].cost() + arm.cost() + leg.cost() 
=  body.cost() + arm.cost() + leg.cost();

这里用“leg对象包住arm对象”来形容leg对象中有arm对象的引用,不过对于一个机器人而言,“leg能包住arm”好像有点魔幻现实的味道。

再举一例

我们不妨再举一个更容易理解的例子:

我们知道,各类绘图软件中都有图层(layer)的概念。

每一个图层都相当于一层透明纸,我们可以在上面任意地画东西,而不会影响其他图层。

把画着东西的图层一层一层地叠放 (相当于“包装”) 起来,我们就可以得到各式各样的画作。

此时,位于上一层的图层就相当于 装饰者 ,而所谓的背景图层就相当于 被装饰者

类图

装饰者模式

其中,

  1. LayerLayerDecorator 为抽象类
  2. LayerDecorator 本质上也是 Layer
  3. description 是各个layer对象的 自我描述
  4. position() 表示layer对象在某个地方画一个图形
  5. RedBackgroundLayerBlueBackgroundLayer 相当于 被装饰者

对应的代码:

Layer.java:

public abstract class Layer {

    String description = "我是抽象layer父类";

    public String getDescription() {
        return description;
    }

    public abstract String position();
}

RedBackgroundLayer.java

public class RedBackgroundLayer extends Layer {


    public RedBackgroundLayer (){
        //从抽象父类layer继承来的description
        description = "我是RedBackgroundLayer->" ;
    }

    @Override
    public String position() {
        return "我在底层画一个红色的layer->";
    }

}

BlueBackgroundLayer.java

public class BlueBackgroundLayer extends Layer {

    public BlueBackgroundLayer() {
        description = "我是一个BlueBackgroundLayer";
    }


    @Override
    public String position() {
        return null;
    }
}

各个装饰者:

RectangleLayerDecorator.java

public class RectangleLayerDecorator extends LayerDecorator {

    Layer layer; 

    //constructor
    public RectangleLayerDecorator(Layer layer) {//这一步很重要
        this.layer = layer;
    }

    @Override
    public String getDescription() {
        return layer.getDescription() + "RectangleLayerDecorator->";
    }

    @Override
    public String position() {
        return layer.position() + "左上角画□->";
    }
}

TriangleLayerDecorator.java

public class TriangleLayerDecorator extends LayerDecorator{

    Layer layer;

    //constructor
    public TriangleLayerDecorator(Layer layer) {
        this.layer = layer;
    }

    @Override
    public String getDescription() {
        return layer.getDescription() + "TriangleLayerDecorator->";
    }

    @Override
    public String position() {
        return layer.position() + "右上角画△->";
    }
}

RoundLayerDecorator.java

public class RoundLayerDecorator extends LayerDecorator {

    Layer layer;
    //constructor
    public RoundLayerDecorator(Layer layer) {
        this.layer = layer;
    }

    @Override
    public String getDescription() {
        return layer.getDescription() + "RoundLayerDecorator->";
    }

    @Override
    public String position() {
        return layer.position() + "右下角画○->";
    }
}

运行Demo

RunDemoTest.java

public class RunDemoTest {

    public static void main (String[] args ){
//Step 1
        Layer backgroundLayer = new RedBackgroundLayer();
        System.out.println(backgroundLayer.getDescription() + backgroundLayer.position());
//Step 2
        //为RedBackgroundLayer装饰一个TriangleLayerDecorator
        Layer multipleLayer = new TriangleLayerDecorator(backgroundLayer);
//Step 3
        //再装饰一个RectangleLayerDecorator
        multipleLayer = new RectangleLayerDecorator(multipleLayer);
//Step 4
        //再装饰一个RoundLayerDecorator
        multipleLayer = new RoundLayerDecorator(multipleLayer);

        System.out.println(multipleLayer.getDescription() + multipleLayer.position());

    }
}

运行结果:

我是RedBackgroundLayer->我在底层画一个红色的layer->
我是RedBackgroundLayer->TriangleLayerDecorator->RectangleLayerDecorator->RoundLayerDecorator->我在底层画一个红色的layer->右上角画△->左上角画□->右下角画○->

运行过程示意图:

装饰者模式

最终得到:

装饰者模式


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

欲罢不能

欲罢不能

[美] 亚当·奥尔特 / 闾佳 / 机械工业出版社 / 2018-4-1 / 59.00元

全面揭秘和解决“行为上瘾”的奠基之作 美国亚马逊分类图书畅销榜第一名 行为上瘾是什么?诱人上瘾的体验是如何设计出来的? 如何远离行为上瘾?如何用行为上瘾做些好事? ◆ 内容简介 ◆ 欢迎来到“行为上瘾”的时代! 我们中近半数人至少有一种“行为上瘾”:无时无刻盯着手机,不断刷朋友圈,通宵追看电视剧集,没日没夜打游戏,频繁查看邮件,用太多时间工作…… 而那些生......一起来看看 《欲罢不能》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码