1-3装饰者模式

来源:互联网 发布:腾讯云数据库怎么建站 编辑:程序博客网 时间:2024/06/11 23:03

装饰者模式

    • 装饰者模式
      • 写在前边的话
      • 定义
      • 特点
      • 案例
        • 星巴克咖啡
        • JAVA IO
        • 手动写一个装饰者模式
      • 装饰者模式的缺点
      • 疑问

写在前边的话

程序要遵循开放-闭合原则,即对扩展开放,对修改闭合。扩展又分为编译期扩展和运行期扩展。其中,继承就是编译期扩展,组合就是运行期扩展。运行期扩展要比编译期更强大.
遵循开放-闭合原则,通常会引入新的抽象层次,增加代码的复杂度而且难以理解(即,不要滥用装饰者模式)。我们需要把最有可能改变的地方应用开放-闭合原则,但那些最有可能改变,这就需要经验(对,这个说不清 )

定义

装饰者将一个对象包装起来以增强新的行为和责任

特点:

  1. 装饰者和被装饰者拥有相同的超类型(可能是抽象类也可能是接口)

  2. 可以用多个装饰类来包装一个对象,装饰类可以包装装饰类或被装饰对象

  3. 因为装饰者和被装饰者拥有相同的抽象类型,因此在任何需要原始对象(被包装)的场合,都可以用装饰过的对象来替代它。

  4. 装饰者可以在被装饰者的行为之前或之后,加上自己的附加行为,以达到特殊目的

  5. 因为对象可以在任何的时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象


案例

星巴克咖啡

案例类图

JAVA I/O

这里写图片描述


这里写图片描述


手动写一个装饰者模式

编写一个装饰者,把输入流中的所有大写都改成小写

public class LowerCaseInputStream extends FilterInputStream{    public LowerCaseInputStream(InputStream in){        super(in);    }    @Override    public int read() throws IOException {        int c = super.read();//从输入流中读取数据的下一个字节。        return (c == -1)? -1 : Character.toLowerCase((char)c);    }    @Override    public int read(byte[] b,int offset,int len) throws IOException{    //将输入流中最多 len 个数据字节读入 byte 数组    int result = super.read(b,offset,len);    for(int i = offset;i< offset + result; i++){        b[i] = (byte)Character.toLowerCase((char)b[i]);    }    return result;}public class InputTest {    public static void main(String[] args) throws IOException {        InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("C:\\Users\\xingzhe\\Desktop\\partner4.sql")));        int c;        while((c = in.read()) >= 0){            System.out.print((char)c);        }        in.close();    }}}

装饰者模式的缺点

  1. 在设计中会有大量的小类,增加理解的难度。例如文件读取类,都是用来包装InputStream类的
  2. 有时客户端依赖于被包装类的特殊类型,而用装饰对象就无法导到这些特殊的东西,导致问题
  3. 一旦使用装饰者模式,不只需要实例化组件(被装饰者),还要把次组件包装到装饰者中,注意,此时可能会有多个装饰者哟。
    例如,FileInputStream
//LineNumberInputStreamInputStream in = new LineNumberInputStream(                    new BufferInputStream(                        new FileInputStream("hello.txt")))

工厂模式和生成器模式会对3这个问题有很大帮助

疑问

  1. 星巴克那个例子中,超类Beverage作为装饰者(Mocha)的一个实例变量,用来记录饮料,然后用调料去装饰;而 JAVA I/O中的LowerCaseInputStream 并没有将超类InputStream作为一个变量
原创粉丝点击