装饰者模式

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

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

装饰者模式

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

思维模式

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

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

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

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

  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. Layer 、 LayerDecorator 为抽象类
  2. LayerDecorator 本质上也是 Layer
  3. description 是各个layer对象的 自我描述
  4. position() 表示layer对象在某个地方画一个图形
  5. RedBackgroundLayer 、 BlueBackgroundLayer 相当于 被装饰者

对应的代码:

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->右上角画△->左上角画□->右下角画○->

运行过程示意图:

装饰者模式

最终得到:

装饰者模式


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

查看所有标签

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

Advanced Web Metrics with Google Analytics, 2nd Edition

Advanced Web Metrics with Google Analytics, 2nd Edition

Brian Clifton / Sybex / 2010-3-15 / USD 39.99

Valuable tips and tricks for using the latest version of Google Analytics Packed with insider tips and tricks, this how-to guide is fully revised to cover the latest version of Google Analytics and sh......一起来看看 《Advanced Web Metrics with Google Analytics, 2nd Edition》 这本书的介绍吧!

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

各进制数互转换器

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

URL 编码/解码
URL 编码/解码

URL 编码/解码