设计模式——装饰者

一、装饰者模式简介

装饰者模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,装饰者模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。是一种 结构型模式

1.基本原理

通过使用装饰者模式,可以在运行时扩充一个类的功能。原理是:增加一个装饰类包裹原来的类,包裹的方式一般是通过在将原来的对象作为修饰类的构造函数的参数。装饰类实现新的功能,但是,在不需要用到新功能的地方,它可以直接调用原来的类中的方法。装饰类必须和原来的类有相同的接口。

装饰者模式是类继承的另外一种选择。类继承在编译时候增加行为,而装饰者模式是在运行时增加行为。

当有几个相互独立的功能需要扩充时,这个区别就变得很重要。在有些面向对象的编程语言中,类不能在运行时被创建,通常在设计的时候也不能预测到有哪几种功能组合。这就意味着要为每一种组合创建一个新类。相反,装饰者模式是面向运行时候的对象实例的,这样就可以在运行时根据需要进行组合。一个装饰者模式的示例是JAVA里的Java I/O Streams的实现。

装饰者模式的UML类图:
请添加图片描述

2.示例代码

砂锅羊肉面 为示例,别问为什么,(╯°□°)╯︵┻━┻

Component相当于Marmite(砂锅)类:

public abstract class Marmite {
    String description = "砂锅";

    public String getDescription() {
        return description;
    }

    public abstract Integer cost();

    @Override
    public String toString() {
        return "这是一碗:" + getDescription() + ",价格:" + cost() + "元";
    }
}

ConcreteComponent是NoddlesMarmite(砂锅面条)类:

public class NoddlesMarmite extends Marmite {

    public NoddlesMarmite() {
        description = "砂锅面条";
    }

    public Integer cost() {
        return 8;
    }
}

Decorator是MaterialDecorator

public abstract class MaterialDecorator extends Marmite {
    public abstract String getDescription();
}

ConcreteDecorator是MuttonMarmite:

public class MuttonMarmite extends MaterialDecorator {
    Marmite marmite;

    public MuttonMarmite(Marmite marmite) {
        this.marmite = marmite;
    }

    @Override
    public String getDescription() {
        return "羊肉、" + marmite.getDescription();
    }

    @Override
    public Integer cost() {
        return 5 + marmite.cost();
    }
}

这是测试代码:

public class MarmiteTest {
    public static void main(String[] args) {
        Marmite marmiteNoddle = new NoddlesMarmite();
        System.out.println(marmiteNoddle.toString());
        Marmite muttonMarmiteNoddle = new MuttonMarmite(marmiteNoddle);
        System.out.println(muttonMarmiteNoddle.toString());
    }
}

二、Java API中装饰者的运用

先看一段demo

public class JavaDemo {
    public static void main(String[] args) {
        System.out.println("请输入一句话:");
        BufferedInputStream bufferedInputStream = new BufferedInputStream(System.in);
        String msg = "wocao";
        try {
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(bufferedInputStream));
            msg = bufferedReader.readLine();
        } catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("输入的是:" + msg);
    }
}

这段代码的功能是将控制台中输入的内容打印出来。

查看java api得知
BufferedInputStream继承的是FilterInputStream,如下图:
请添加图片描述
FilterInputStream继承的是InputStream,并且有InputStream对象的一个引用
请添加图片描述
由此可以得出
InputStream相当于Component,FileterInputStream相当于Decorator,BufferedInputStream相当于ConcreteDecorator,System.in相当于ConcreteComponent。

三、自己实现一个关于InputStream的ConcreteDecorator

talk is cheap, show me the code

public class LowerCaseInputStream extends FilterInputStream {

    public LowerCaseInputStream(InputStream in){
        super(in);
    }

    @Override
    public int read() throws IOException {
        int c=super.read();
        return (c==-1?c:Character.toLowerCase((char)c));
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int result=super.read(b,off,len);
        for(int i=off;i<off+result;i++){
            b[i]=(byte)Character.toLowerCase((char)b[i]);
        }
        return result;
    }
}

不想解释了,心累
看不懂的,送你一幅图:
请添加图片描述

---------------------------------------EOF--------------------------------------

参考资料:

  • https://zh.wikipedia.org/wiki/%E4%BF%AE%E9%A5%B0%E6%A8%A1%E5%BC%8F
  • Head First设计模式

我的心愿是世界和平!~( ゜▽゜)つロ

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值