• 《JAVA与模式》之装修者模式


    装饰者模式

    动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

    具体被装饰者和抽象装饰类都继承于抽象被装饰者类,继承的是类型,而不是行为。行为来自装饰者和基础组件,或与其他装饰者之间的组合关系。

    装饰模式的角色

      抽象构件角色(Component):给出一个抽象接口,以规范准备接收附加责任的对象。

      具体构件角色(Concrete Component):定义将要接收附加责任的类。

      装饰角色(Decorator):持有一个构件(Component)对象的引用,并定义一个与抽象构件接口一致的接口。

      具体装饰角色(Concrete Decorator):负责给构件对象“贴上”附加的责任。


    装饰模式的特点

      装饰对象和真实对象有相同的接口。这样客户端对象就可以以和真实对象相同的方式和装饰对象交互。

      装饰对象包含一个真实对象的引用(reference)。

      装饰对象接收所有来自客户端的请求,它把这些请求转发给真实的对象。

      装饰对象可以在转发这些请求之前或之后附加一些功能。

      这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。

    代码

     1 public class Zhuangxiuzhe {
     2     public static void main(String[] args) {
     3         Zhuangxiuzhe zhuangxiuzhe=new Zhuangxiuzhe();
     4         Component component=zhuangxiuzhe.new ConcreteComponent();
     5         Component decorator=zhuangxiuzhe.new ConcreteDecorator1(component);
     6         decorator.doMethod();
     7         Component decorator2=zhuangxiuzhe.new ConcreteDecorator2(decorator);
     8         decorator2.doMethod();
     9         
    10     }
    11 
    12     interface Component {
    13 
    14         public void doMethod();
    15 
    16     }
    17 
    18     class ConcreteComponent implements Component {
    19 
    20         public void doMethod() {
    21             System.out.println("一般操作");
    22 
    23         }
    24 
    25     }
    26     abstract class  Decorator implements Component{
    27         
    28         protected Component component;
    29         public Decorator(Component component){
    30             this.component=component;
    31         }
    32             
    33         
    34     }
    35     class ConcreteDecorator1 extends Decorator{
    36 
    37         public ConcreteDecorator1(Component component) {
    38             super(component);
    39             
    40         }
    41         public void test1(){
    42             System.out.println("ConcreteDecorator1 额外操作");
    43         }
    44 
    45         public void doMethod() {
    46             super.component.doMethod();
    47             test1();
    48         }
    49     }
    50     class ConcreteDecorator2 extends Decorator{
    51         
    52         public ConcreteDecorator2(Component component) {
    53             super(component);
    54             
    55         }
    56         
    57         public void doMethod() {
    58             super.component.doMethod();
    59             test2();
    60         }
    61         
    62         public void test2(){
    63             System.out.println("ConcreteDecorator2 额外操作");
    64         }
    65     }
    66     
    67 
    68 }

    执行结果

    一般操作
    ConcreteDecorator1 额外操作
    一般操作
    ConcreteDecorator1 额外操作
    ConcreteDecorator2 额外操作


     突然发现装修者模式跟责任链模式有点相同,自身都引用了抽象类,这样可以调用传入的包装类

    区别在于功能上:责任链强调的是请求由谁来处理,而装修者模式则是对引入的对象的现有功能进行包装,增强改变

    Java IO中的装饰模式

      在IO中,具体构件角色是节点流,装饰角色是过滤流

      FilterInputStream和FilterOutputStream是装饰角色,而其他派生自它们的类则是具体装饰角色。

    我们来看看代码

    抽象角色类InputStream

    1 public abstract class InputStream implements Closeable {
    2 
    3 
    4 //实现了read等方法
    5 public int read(byte b[]) throws IOException {
    6     return read(b, 0, b.length);
    7     }
    8 
    9 }

    具体角色类FileInputStream

    1 public
    2 class FileInputStream extends InputStream{
    3 
    4 
    5 }

    抽象包装类FilterInputStream

     1 public
     2 class FilterInputStream extends InputStream {
     3     /**
     4      * The input stream to be filtered. 
     5      */
     6     protected volatile InputStream in;
     7 
     8 
     9 protected FilterInputStream(InputStream in) {
    10     this.in = in;
    11     }
    12 
    13  public int read() throws IOException {
    14     return in.read();
    15     }
    16 
    17 
    18 }

    具体包装类BufferedInputStream

     1 public
     2 class BufferedInputStream extends FilterInputStream {
     3 
     4 public BufferedInputStream(InputStream in) {
     5     this(in, defaultBufferSize);
     6     }
     7 
     8 //完成了设置抽象角色类的映射
     9  public BufferedInputStream(InputStream in, int size) {
    10     super(in);
    11         if (size <= 0) {
    12             throw new IllegalArgumentException("Buffer size <= 0");
    13         }
    14     buf = new byte[size];
    15     }
    16 
    17 //read方法中调用fill()
    18  public synchronized int read() throws IOException {
    19     if (pos >= count) {
    20         fill();
    21         if (pos >= count)
    22         return -1;
    23     }
    24     return getBufIfOpen()[pos++] & 0xff;
    25     }
    26  private void fill() throws IOException {
    27         byte[] buffer = getBufIfOpen();
    28     if (markpos < 0)
    29         pos = 0;        /* no mark: throw away the buffer */
    30     else if (pos >= buffer.length)    /* no room left in buffer */
    31         if (markpos > 0) {    /* can throw away early part of the buffer */
    32         int sz = pos - markpos;
    33         System.arraycopy(buffer, markpos, buffer, 0, sz);
    34         pos = sz;
    35         markpos = 0;
    36         } else if (buffer.length >= marklimit) {
    37         markpos = -1;    /* buffer got too big, invalidate mark */
    38         pos = 0;    /* drop buffer contents */
    39         } else {        /* grow buffer */
    40         int nsz = pos * 2;
    41         if (nsz > marklimit)
    42             nsz = marklimit;
    43         byte nbuf[] = new byte[nsz];
    44         System.arraycopy(buffer, 0, nbuf, 0, pos);
    45                 if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
    46                     // Can't replace buf if there was an async close.
    47                     // Note: This would need to be changed if fill()
    48                     // is ever made accessible to multiple threads.
    49                     // But for now, the only way CAS can fail is via close.
    50                     // assert buf == null;
    51                     throw new IOException("Stream closed");
    52                 }
    53                 buffer = nbuf;
    54         }
    55         count = pos;
    56     int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
    57         if (n > 0)
    58             count = n + pos;
    59     }
    60 
    61 
    62 }

    fill()方法中除了自身操作外,我们看到了 int n = getInIfOpen().read(buffer, pos, buffer.length - pos);

    1  private InputStream getInIfOpen() throws IOException {
    2         InputStream input = in;
    3     if (input == null)
    4         throw new IOException("Stream closed");
    5         return input;
    6     }

    在看看getInIfOpen()方法,我们就明白了 整个的过程

    参考地址:

    http://www.cnblogs.com/mengdd/archive/2013/02/12/2910302.html

    http://blog.csdn.net/cai1213/article/details/8003445

    http://xubindehao.iteye.com/blog/474636

  • 相关阅读:
    VMware虚拟机中常见的问题汇总
    Windows10下安装VMware虚拟机并搭建CentOS系统环境
    myeclipse2017使用总结
    mybatis如何通过接口查找对应的mapper.xml及方法执行详解
    (转)将SVN从一台服务器迁移到另一台服务器(Windows Server VisualSVN Server)
    (转)Maven中的库(repository)详解 ---repository配置查找构件(如.jar)的远程库
    Git知识讲解
    (转)MyEclipse中使用git
    在SpringBoot中添加Logback日志处理
    (转)Spring Boot干货系列:(七)默认日志logback配置解析
  • 原文地址:https://www.cnblogs.com/draem0507/p/3797246.html
Copyright © 2020-2023  润新知