前言:
来源于《head first 设计模式》。当作读书笔记了,这次看的是第三章装饰者模式。看得有点上瘾。。。抽出了点时间来总结一下。
装饰者模式的概念
动态地将责任附加到对象之上。想要扩展功能,装饰者提供有别于继承的另一种选择。
head fitst基本操作举个例子
head first里面举了两个例子,一个是星巴克一个我们熟悉的java i/o包。这里为了方便就用java i/o来展示我们的装饰者模式吧。
通用的观察者模式的uml图
惯例贴一下uml图,这是通用的观察者模式的uml图,我们看完它再来了解java i/o的会更好理解
Component:作用是规定了同一个父类,让每一个组件都可以单独使用或者被装饰者包含起来。
ConcreteComponent:这是我们要动态地加上新行为的对象,继承与Component.
Decorator:这是装饰者共同需要实现的接口或者继承的父类,它使每个装饰者都带有一个或者说是包含一个组件,即有一个实例变量来保存某一Component
ConcreteDecoraror:装饰者咯,可以拓展新的方法或者增加新的行为在旧的行为后面
Java i/o的uml:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1h1B6wlP-1586688264037)(https://imgblog.csdnimg.cn/20200412183344793.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2F3YWtlX2xxaA==,size_16,color_FFFFFF,t_70)]
并没有把所有的类都写出了,写了几个点名关系即可了。
InputStream:相当于上方的component
FileInputStream:相当于被修饰的对象
StringBufferInputStream:相当于被修饰的对象
FilterInputStream:修饰者共同的父类了,里面包含了一个inputstream实例。
LowerCaseInputStream代码:
public class LowerCaseInputStream extends FilterInputStream {
protected LowerCaseInputStream(InputStream in) {
super(in);
}
//针对字节流
public int read() throws IOException{
int c=super.read();
return (c==-1?c:Character.toLowerCase(((char)c)));
}
//针对字节数组
public int read(byte[] b,int offset,int len) throws IOException {
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) {
int c;
try {
InputStream in=new LowerCaseInputStream(
new BufferedInputStream(
new FileInputStream("./test.txt")));
while ((c=in.read())>=0){
System.out.print((char)c);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结:
InputStream in=new LowerCaseInputStream(
new BufferedInputStream(
new FileInputStream("./test.txt")));
这是平常我们书写一个读取类基本的写法把,类似于套娃。我们可以理解为我们先用BufferedInputStream修饰了组件FileInputStream,再用我们自己的LowerCaseInputStream修饰了BufferedInputStream。read的方法的调用就先调用FileInputStream从文件中读取然后到BufferedInputStream用字符流再到LowerCaseInputStream转化为小写,这样统分体现了装饰者模式对方法的扩展,又不会影响上层代码,同时对于java i/o这种类别特别多已经功能又重复,或者再某个类基础上加强的,最为适用。
装饰者模式简单来讲其实就是:动态的给一个对象添加一些额外的功能,而无需修改上层代码。