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
- javaIO的装饰者模式
- JavaIO之装饰器模式的理解
- JavaIO中的装饰者模式(Wrapper)
- javaIO装饰者模式类图
- javaIO(1):OutputStream和FileOutputStream源码分析及“装饰者模式”在IO中的应用
- java设计模式--装饰器设计模式(javaIO设计使用)
- 设计模式系列-javaIO流与装饰模式
- 从装饰设计模式角度学习JavaIO字节流
- 装饰者模式的由来
- java的装饰者模式
- 装饰者模式的分析
- 装饰者模式的应用
- 自已理解的装饰者模式
- 关于装饰者模式的个人理解
- 装饰者模式浅浅的理解
- java io 装饰者模式的应用
- 我对装饰者模式的理解
- 笔记:装饰者模式的初步理解
- 关于时间转换-----angularjs
- auto_ptr实现原理
- POJ 2976 Dropping tests 01分治
- Linux基础命令
- Python的函数重载
- javaIO的装饰者模式
- Sql Server Sql语句学习
- xml可视化编辑器
- [LeetCode]62. Unique Paths
- 【如何学习一门新语言】HTML5基础培训总结
- Jmeter查看结果树响应结果unicode转成中文显示
- 学习笔记-Android AIDL传递对象数据
- js 鼠标右击事件
- 汉诺塔问题