设计模式-装饰者模式

发布于 2023-04-25 21:37:27 字数 4115 浏览 73 评论 0

上一篇说到适配器模式,这次说它的同胞兄弟——装饰器模式。我们有时会遇到需要对类自身方法功能的累加,比如 FilterInputStream 需要 InputStream 其他子类的read 上累加功能。


举例

装饰器通常需要一个源,即你认为需要包装或基于此添加功能的类,源需要与装饰器同父类。

如下代码,源 DecoratorTargetSource 被实例化时并不需要传入任何 DecoratorTarget 类型,而 Decorator1Decorator2Decorator3 等装饰类实例化时需要 DecoratorTarget 类型对象。

//基类(接口)
public interface DecoratorTarget {
    void read(byte[] bs);
}
//源基类
public class DecoratorTargetSource implements DecoratorTarget {

    @Override
    public void read(byte[] bs) {}

}
//源基类装饰器1
public class Decorator1 implements DecoratorTarget {

    protected DecoratorTarget target;
    public Decorator1(DecoratorTarget target) {
        this.target = target;
    }
    @Override
    public void read(byte[] bs) {
        // ...
        target.read(bs);
        // ...
    }

}
//源基类装饰器2
public class Decorator2 implements DecoratorTarget {

    protected DecoratorTarget target;
    public Decorator2(DecoratorTarget target) {
        this.target = target;
    }
    @Override
    public void read(byte[] bs) {
        // ...
        target.read(bs);
        // ...
    }

}
//源基类装饰器3
public class Decorator3 extends Decorator1 {

    public Decorator3(DecoratorTarget target) {
        super(target);
        this.target = target;
    }
    @Override
    public void read(byte[] bs) {
        // ...
        target.read(bs);
        // ...
    }

}

public class DecoratorTemplate {    
    public static void main(String[] args) {
        DecoratorTarget target = new Decorator1(new Decorator3(new Decorator2(new DecoratorTargetSource())));
    }
}

JDK 中的装饰器模式

Java 中最为人所知的装饰器模式,莫过于 IO 框架。源码如下:

//基类
public abstract class InputStream implements Closeable {
    //...
}
//装饰器FilterInputStream
public class FilterInputStream extends InputStream {
    protected volatile InputStream in;
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }
}
//装饰器BufferedInputStream,继承于FilterInputStream
public class BufferedInputStream extends FilterInputStream {
    private InputStream getInIfOpen() throws IOException {
        InputStream input = in;
        if (input == null)
            throw new IOException("Stream closed");
        return input;
    }

    private void fill() throws IOException {
        // ...
        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
        // ...
    }

    public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos++] & 0xff;
    }
}
//源
public class FileInputStream extends InputStream {
    public FileInputStream(String name) throws FileNotFoundException {
        this(name != null ? new File(name) : null);
    }
    public FileInputStream(File file) throws FileNotFoundException {
        String name = (file != null ? file.getPath() : null);
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            security.checkRead(name);
        }
        if (name == null) {
            throw new NullPointerException();
        }
        if (file.isInvalid()) {
            throw new FileNotFoundException("Invalid file path");
        }
        fd = new FileDescriptor();
        fd.incrementAndGetUseCount();
        this.path = name;
        open(name);
    }
    public FileInputStream(FileDescriptor fdObj) {
        SecurityManager security = System.getSecurityManager();
        if (fdObj == null) {
            throw new NullPointerException();
        }
        if (security != null) {
            security.checkRead(fdObj);
        }
        fd = fdObj;
        path = null;
        fd.incrementAndGetUseCount();
    }
}

上述源码中,FileInputStream 并没有参数包含 InputStream 类型,所以可以看成是一个源,那么 FilterInputStream 及其子类 BufferedInputStream 则是装饰器。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
25 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文