javaIO的装饰者模式

来源:互联网 发布:富士施乐2011网络扫描 编辑:程序博客网 时间:2024/05/16 15:35

装饰者模式的uml

  • 通过继承和组合的方式来设计类的修饰作用
  • 在继承的基础上,通过引用让对象具有多重修饰(拥有其他子类的方法)的特性。
    这里写图片描述
    这个类图是《Head first 设计模式》上的例子
    装饰者的魔力主要在于CondimentDecorator的身上,它是抽象的装饰者类。继承CondimentDecorator在构造方法上都引用了Baverage抽象类。

抽象的Beverage类

public abstract class Beverage {    //星巴兹咖啡店新增了小杯、中杯、大杯的咖啡规格。    public static final int small = 1;    public static final int middle = 2;    public static final int large = 3;    String description;    private double sizeCost = 0D;    private String sizeDescription = "";    public void setSize(int size){        if (size == small){            sizeCost = 0.1;            sizeDescription = "小杯";        }else if (size == middle){            sizeCost = 0.2;            sizeDescription = "中杯";        }else if (size == large){            sizeCost = 0.3;            sizeDescription = "大杯";        }    }    public Double getSize(){        return sizeCost;    }    public String getDescription(){        return sizeDescription + this.description;    }    //不同的价格,由子类来说明    public abstract Double cost();}

不具有装饰的子类(只列举一个)

public class DarkRoast extends Beverage{    public DarkRoast(){        description = "深焙咖啡";    }    public Double cost() {        return super.getSize() + 0.89;    }}

装饰者的抽象类

可以根据自身业务,来定义要实现的抽象方法

public abstract class CondimentDecorator extends Beverage{    //对被装饰的了饮料的描述    public abstract String getDescription();}

具有装饰效果的子类

public class Mocha extends CondimentDecorator {   //引入父类,让装饰者对象都有其父类的特性    private Beverage beverage;    private Mocha(){}    public Mocha(Beverage beverage){        this.beverage = beverage;    }    public String getDescription() {        return this.beverage.getDescription() + ", 摩卡";    }    public Double cost() {        return this.beverage.cost() + 0.2;    }}

装饰者的魔力体验

public class DecoratorMain {    public static void main(String[] args) {        //来大杯的双倍摩卡综合咖啡        Beverage beverage = new HouseBlend();        beverage.setSize(3);        beverage = new Mocha(beverage);        beverage = new Mocha(beverage);        System.out.println("描述:" + beverage.getDescription() + "。 价格:"+beverage.cost());    }}

以上将一个子类对象经过多重修饰,获得一个想要达到的目标。

javaIO中的装饰者模式设计

java对io操作的API中有根据读取方向分为输入流(InputStream)和输出流(OutputStream),我们从InputStream来开始分析。

InputStream的uml图

这里写图片描述

从java的io包中找出*InputStream类来对其进行uml设计关系的分析。
* 具有装饰功能的类都继承自FilterInputStream类,他们的子类都持有InputStream类的引用
* 其余的子类对象例如FileInputStream类和ByteArrayInputStream类都是正常的子类实现,直接继承自InputStream。

分析BufferedInputStream类

从调用入口开始入手分析

//inputStream只能按照字节来读取,因此读取中文的时候会出现乱码    public void useBufferedInputStream() throws IOException {        String str = "fdsggdsk";        byte[] bytes = str.getBytes("utf-8");        BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(bytes));        int c ;        StringBuffer sb = new StringBuffer();        while ((c = bis.read()) >= 0 ){            sb.append((char) c);        }        System.out.println("sb.toString() = " + sb.toString());    }

这里创建了两个InputStream子类的实例
1. new ByteArrayInputStream(bytes)
2. new BufferedInputStream(new ByteArrayInputStream(bytes))
3. 调用BufferedInputStream的read方法
ByteArrayInputStream的read方法是一个字节一个字节的读取内容,而BufferInputStream的read方法,是将所有的字节缓冲到buf[]数组中,然后再依次读取
通过源码可以了解

public synchronized int read() throws IOException {//先判断数组指针和count是否相等,如果pos == count,当使用//read()方法读取到缓冲区的末尾时,会使用fill()方法再次预先读入//一部分字节        if (pos >= count) {            fill();            if (pos >= count)                return -1;        }        return getBufIfOpen()[pos++] & 0xff;    }
 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)) {                    // Can't replace buf if there was an async close.                    // Note: This would need to be changed if fill()                    // is ever made accessible to multiple threads.                    // But for now, the only way CAS can fail is via close.                    // assert buf == null;                    throw new IOException("Stream closed");                }                buffer = nbuf;            }        count = pos;        //这里调用InputStream的read方法,哪个子类实现该方法,        //就调用它的实现。例如ByteArrayInputStream.read()        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);        if (n > 0)            count = n + pos;

以上就是javaIO的装饰模式的实现例子。我们也可以通过集成字FilterInputStream来特定的IO读取方式。
实现一个将大写字母转换成小写的InputStream

LowerCaseInputStream类的实现

简单的实现,只实现了read()和read(byte[] b, int off, int len) 方法就可以了

public class LowerCaseInputStream extends FilterInputStream {    /**     * Creates a <code>FilterInputStream</code>     * by assigning the  argument <code>in</code>     * to the field <code>this.in</code> so as     * to remember it for later use.     *     * @param in the underlying input stream, or <code>null</code> if     *           this instance is to be created without an underlying stream.     */    protected LowerCaseInputStream(InputStream in) {        super(in);    }    @Override    public int read() throws IOException {        int read = super.read();        return read == -1 ? -1 : Character.toLowerCase((char)read);    }    @Override    public int read(byte[] b, int off, int len) throws IOException {        int read = super.read(b, off, len);        for (int i = off; i < off + len; i++){            b[i] = (byte) Character.toLowerCase((char) b[i]);        }        return read;    }}

参考博客
http://blog.csdn.net/songwei128/article/details/23355045

原创粉丝点击