1-3装饰者模式

xiaoxiao2021-02-28  88

装饰者模式

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

写在前边的话

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

定义

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

特点:

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

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

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

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

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


案例

星巴克咖啡

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(); } } }

装饰者模式的缺点

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

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

疑问

星巴克那个例子中,超类Beverage作为装饰者(Mocha)的一个实例变量,用来记录饮料,然后用调料去装饰;而 JAVA I/O中的LowerCaseInputStream 并没有将超类InputStream作为一个变量
转载请注明原文地址: https://www.6miu.com/read-58821.html

最新回复(0)