[TOC]
概述:
5分钟理解设计模式系列,将通过解决实际问题,来带您理解设计模式,本文希望带您搞懂的3个问题是:
1.什么是装饰器模式?
2.通过剖析Java IO类库,理解装饰器模式?
3.装饰器模式和代理模式的区别?
1.什么是装饰器模式?
装饰器模式(Decorator)主要用法是动态增强类的功能,就这一点而言,装饰器模式和代理模式较为相似。后面我们会对着重讨论这两种模式的异同。下面我们举一个生活中的例子:
一个蛋糕,我们为它添加水果,它就变成了水果蛋糕。
一个水果蛋糕,我们为它插上蜡烛,它就变成了生日蛋糕。
如果你对java io类库比较了解的话,可以知道,java io类库中大量运用了装饰器模式,接下来我们会通过阅读java io类库,来一起深入理解装饰器模式。
2.通过剖析Java IO类库,理解装饰器模式?
首先我们应该对java io类库有一个大致的了解。我们可以按照两个维度,将它分为4类。

而针对不同的使用场景,java io又在这四个父类之上,扩展出了很多子类。

我们来看一段读取数据的代码:
InputStream in = new FileInputStream("/test.txt");
InputStream bin = new BufferedInputStream(in);
byte[] data = new byte[128];
while (bin.read(data) != -1) {
//省略具体操作
}
我们可以看到,java io使用的是一种组合的方式,来扩展fileInputStream的功能。那么使用继承可不可以呢?
组合 vs 继承
我们经常会听到这样一种说法,组合优于继承,在实际的开发过程中,这句话往往是没有问题的,我们很容易为了节省一部分代码,滥用继承,导致代码结构混乱。但是本着怀疑一切的思想,我们在这里还是来分析一下,为什么java io会选择组合,而不是继承。
为什么java io会选择组合,而不是继承。
我们可以看到,java io具有很多个子类,这些子类适用于不同的场景,如果使用继承的话,那么就需要派生大量的子类,如果是多种场景叠加的情况,那么类的继承关系将变得非常复杂,代码即不好扩展, 也不好维护。
其实通过继承来扩展功能也是可以的,比如tomcat的连接器。它将I/O模型和应用层协议,通过继承的方式进行了功能的组合。
这里我觉得一方面是I/O模型和应用层的关系相对固定,只能两两组合,另一方面,它们的数量也是可控的,所以这里tomcat使用了继承的方式来扩展功能。
通过上面的论述,我们知道了java io是通过组合的方式,来实现装饰器模式,从而实现一种功能的增强。
源码解析
public abstract class InputStream {
//...
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
//...
}
public long skip(long n) throws IOException {
//...
}
public int available() throws IOException {
return 0;
}
public void close() throws IOException {}
public synchronized void mark(int readlimit) {}
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
public boolean markSupported() {
return false;
}
}
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
public long skip(long n) throws IOException {
return in.skip(n);
}
public int available() throws IOException {
return in.available();
}
public void close() throws IOException {
in.close();
}
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
public synchronized void reset() throws IOException {
in.reset();
}
public boolean markSupported() {
return in.markSupported();
}
}
FilterInputStream是一个java io抽象出来的装饰器父类,主要是用于实现一些InputStream中的默认实现,这样其他的装饰器类就可以专注于实现自己想要增强功能的方法。这种设计方法也被广泛运用在各种框架中。

3.装饰器模式和代理模式的区别?
它们的实现方式都是组合,主要区别是:
装饰器模式是对类原有功能的增强(读数据增强成加缓存,批量读数据)。
代理模式是对类原有功能的扩展(为执行方法增加记录日志的功能)。
最后,期待您的订阅和点赞,专栏每周都会更新,希望可以和您一起进步,同时也期待您的批评与指正!
[TOC]
概述:
5分钟理解设计模式系列,将通过解决实际问题,来带您理解设计模式,本文希望带您搞懂的3个问题是:
1.什么是装饰器模式?
2.通过剖析Java IO类库,理解装饰器模式?
3.装饰器模式和代理模式的区别?
1.什么是装饰器模式?
装饰器模式(Decorator)主要用法是动态增强类的功能,就这一点而言,装饰器模式和代理模式较为相似。后面我们会对着重讨论这两种模式的异同。下面我们举一个生活中的例子:
一个蛋糕,我们为它添加水果,它就变成了水果蛋糕。
一个水果蛋糕,我们为它插上蜡烛,它就变成了生日蛋糕。
如果你对java io类库比较了解的话,可以知道,java io类库中大量运用了装饰器模式,接下来我们会通过阅读java io类库,来一起深入理解装饰器模式。
2.通过剖析Java IO类库,理解装饰器模式?
首先我们应该对java io类库有一个大致的了解。我们可以按照两个维度,将它分为4类。

而针对不同的使用场景,java io又在这四个父类之上,扩展出了很多子类。

我们来看一段读取数据的代码:
InputStream in = new FileInputStream("/test.txt");
InputStream bin = new BufferedInputStream(in);
byte[] data = new byte[128];
while (bin.read(data) != -1) {
//省略具体操作
}
我们可以看到,java io使用的是一种组合的方式,来扩展fileInputStream的功能。那么使用继承可不可以呢?
组合 vs 继承
我们经常会听到这样一种说法,组合优于继承,在实际的开发过程中,这句话往往是没有问题的,我们很容易为了节省一部分代码,滥用继承,导致代码结构混乱。但是本着怀疑一切的思想,我们在这里还是来分析一下,为什么java io会选择组合,而不是继承。
为什么java io会选择组合,而不是继承。
我们可以看到,java io具有很多个子类,这些子类适用于不同的场景,如果使用继承的话,那么就需要派生大量的子类,如果是多种场景叠加的情况,那么类的继承关系将变得非常复杂,代码即不好扩展, 也不好维护。
其实通过继承来扩展功能也是可以的,比如tomcat的连接器。它将I/O模型和应用层协议,通过继承的方式进行了功能的组合。
这里我觉得一方面是I/O模型和应用层的关系相对固定,只能两两组合,另一方面,它们的数量也是可控的,所以这里tomcat使用了继承的方式来扩展功能。
通过上面的论述,我们知道了java io是通过组合的方式,来实现装饰器模式,从而实现一种功能的增强。
源码解析
public abstract class InputStream {
//...
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
//...
}
public long skip(long n) throws IOException {
//...
}
public int available() throws IOException {
return 0;
}
public void close() throws IOException {}
public synchronized void mark(int readlimit) {}
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
public boolean markSupported() {
return false;
}
}
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
public long skip(long n) throws IOException {
return in.skip(n);
}
public int available() throws IOException {
return in.available();
}
public void close() throws IOException {
in.close();
}
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
public synchronized void reset() throws IOException {
in.reset();
}
public boolean markSupported() {
return in.markSupported();
}
}
FilterInputStream是一个java io抽象出来的装饰器父类,主要是用于实现一些InputStream中的默认实现,这样其他的装饰器类就可以专注于实现自己想要增强功能的方法。这种设计方法也被广泛运用在各种框架中。

3.装饰器模式和代理模式的区别?
它们的实现方式都是组合,主要区别是:
装饰器模式是对类原有功能的增强(读数据增强成加缓存,批量读数据)。
代理模式是对类原有功能的扩展(为执行方法增加记录日志的功能)。
最后,期待您的订阅和点赞,专栏每周都会更新,希望可以和您一起进步,同时也期待您的批评与指正!
[TOC]
概述:
5分钟理解设计模式系列,将通过解决实际问题,来带您理解设计模式,本文希望带您搞懂的3个问题是:
1.什么是装饰器模式?
2.通过剖析Java IO类库,理解装饰器模式?
3.装饰器模式和代理模式的区别?
1.什么是装饰器模式?
装饰器模式(Decorator)主要用法是动态增强类的功能,就这一点而言,装饰器模式和代理模式较为相似。后面我们会对着重讨论这两种模式的异同。下面我们举一个生活中的例子:
一个蛋糕,我们为它添加水果,它就变成了水果蛋糕。
一个水果蛋糕,我们为它插上蜡烛,它就变成了生日蛋糕。
如果你对java io类库比较了解的话,可以知道,java io类库中大量运用了装饰器模式,接下来我们会通过阅读java io类库,来一起深入理解装饰器模式。
2.通过剖析Java IO类库,理解装饰器模式?
首先我们应该对java io类库有一个大致的了解。我们可以按照两个维度,将它分为4类。

而针对不同的使用场景,java io又在这四个父类之上,扩展出了很多子类。

我们来看一段读取数据的代码:
InputStream in = new FileInputStream("/test.txt");
InputStream bin = new BufferedInputStream(in);
byte[] data = new byte[128];
while (bin.read(data) != -1) {
//省略具体操作
}
我们可以看到,java io使用的是一种组合的方式,来扩展fileInputStream的功能。那么使用继承可不可以呢?
组合 vs 继承
我们经常会听到这样一种说法,组合优于继承,在实际的开发过程中,这句话往往是没有问题的,我们很容易为了节省一部分代码,滥用继承,导致代码结构混乱。但是本着怀疑一切的思想,我们在这里还是来分析一下,为什么java io会选择组合,而不是继承。
为什么java io会选择组合,而不是继承。
我们可以看到,java io具有很多个子类,这些子类适用于不同的场景,如果使用继承的话,那么就需要派生大量的子类,如果是多种场景叠加的情况,那么类的继承关系将变得非常复杂,代码即不好扩展, 也不好维护。
其实通过继承来扩展功能也是可以的,比如tomcat的连接器。它将I/O模型和应用层协议,通过继承的方式进行了功能的组合。
这里我觉得一方面是I/O模型和应用层的关系相对固定,只能两两组合,另一方面,它们的数量也是可控的,所以这里tomcat使用了继承的方式来扩展功能。
通过上面的论述,我们知道了java io是通过组合的方式,来实现装饰器模式,从而实现一种功能的增强。
源码解析
public abstract class InputStream {
//...
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
//...
}
public long skip(long n) throws IOException {
//...
}
public int available() throws IOException {
return 0;
}
public void close() throws IOException {}
public synchronized void mark(int readlimit) {}
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
public boolean markSupported() {
return false;
}
}
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
public long skip(long n) throws IOException {
return in.skip(n);
}
public int available() throws IOException {
return in.available();
}
public void close() throws IOException {
in.close();
}
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
public synchronized void reset() throws IOException {
in.reset();
}
public boolean markSupported() {
return in.markSupported();
}
}
FilterInputStream是一个java io抽象出来的装饰器父类,主要是用于实现一些InputStream中的默认实现,这样其他的装饰器类就可以专注于实现自己想要增强功能的方法。这种设计方法也被广泛运用在各种框架中。

3.装饰器模式和代理模式的区别?
它们的实现方式都是组合,主要区别是:
装饰器模式是对类原有功能的增强(读数据增强成加缓存,批量读数据)。
代理模式是对类原有功能的扩展(为执行方法增加记录日志的功能)。
最后,期待您的订阅和点赞,专栏每周都会更新,希望可以和您一起进步,同时也期待您的批评与指正!