标签:简单 ring sys 演示 sequence tin inpu 地方 掌握
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
在类图中,各个角色的说明如下:
//抽象构件 public abstract class Component { // 抽象的方法 public abstract void cost(); }
//具体基础构件 public class ConcreteComponent extends Component{ public void cost(){ System.out.println("这是具体基础构件"); } }
//抽象装饰角色 public abstract class Decorator extends Component{ private Component component = null; public Decorator(Component component){ this.component = component; } @Override public void cost(){ this.component.cost(); } }
//具体装饰角色 public class ConcreteDecorator extends Decorator{ public ConcreteDecorator(Component component){ super(component); } // 定义自己的修饰逻辑 private void decorateMethod(){ System.out.println("定义自己的修饰逻辑"); } // 重写父类的方法 public void cost(){ this.decorateMethod(); super.cost(); } }
public class DecoratorDemo { public static void main(String[] args){ Component component = new ConcreteComponent(); // 第一次修饰,比如,加一个花边 component = new ConcreteDecorator(component); // 第二次修饰,比如,加一个图片 component = new ConcreteDecorator(component); // 修饰后运行,将所有加一起 component.cost(); } }
前面说过IO用的就是装饰器
InputStream作为抽象构件,其下面大约有如下几种具体基础构件,从不同的数据源产生输入:
FilterInputStream作为装饰器在JDK中是一个普通类,其下面有多个具体装饰器比如BufferedInputStream、DataInputStream等。我们以BufferedInputStream为例,使用它就是避免每次读取时都进行实际的写操作,起着缓冲作用。我们可以在这里稍微深入一下,站在源码的角度看下。
FilterInputStream内部封装了基础构件:
protected volatile InputStream in;
而BufferedInputStream在调用其read()读取数据时会委托基础构件来进行更底层的操作,而它自己所起的装饰作用就是缓冲,在源码中可以很清楚的看到这一切:
public synchronized int read() throws IOException { if (pos >= count) { fill(); if (pos >= count) return -1; } return getBufIfOpen()[pos++] & 0xff; } private void fill() throws IOException { byte[] buffer = getBufIfOpen(); if (markpos < 0) pos = 0; /* no mark: throw away the buffer */ else if (pos >= buffer.length) /* no room left in buffer */ if (markpos > 0) { /* can throw away early part of the buffer */ int sz = pos - markpos; System.arraycopy(buffer, markpos, buffer, 0, sz); pos = sz; markpos = 0; } else if (buffer.length >= marklimit) { markpos = -1; /* buffer got too big, invalidate mark */ pos = 0; /* drop buffer contents */ } else if (buffer.length >= MAX_BUFFER_SIZE) { throw new OutOfMemoryError("Required array size too large"); } else { /* grow buffer */ int nsz = (pos <= MAX_BUFFER_SIZE - pos) ? pos * 2 : MAX_BUFFER_SIZE; if (nsz > marklimit) nsz = marklimit; byte nbuf[] = new byte[nsz]; System.arraycopy(buffer, 0, nbuf, 0, pos); if (!bufUpdater.compareAndSet(this, buffer, nbuf)) { throw new IOException("Stream closed"); } buffer = nbuf; } count = pos; // 看这行就行了,委托基础构件来进行更底层的操作 int n = getInIfOpen().read(buffer, pos, buffer.length - pos); if (n > 0) count = n + pos; } private InputStream getInIfOpen() throws IOException { InputStream input = in; if (input == null) throw new IOException("Stream closed"); return input; }
这部分的代码很多,这里没有必要考虑这段代码的具体逻辑,只需要看到在BufferedInputStream的read方法中通过getInIfOpen()获取基础构件从而委托其进行更底层的操作(在这里是读取单个字节)就可以说明本文所要说的一切了。至于I/O类库中的其他设计诸如OutputStream、Writer、Reader,是一致的
标签:简单 ring sys 演示 sequence tin inpu 地方 掌握
原文地址:https://www.cnblogs.com/xing1/p/14594915.html