|--什么是装饰模式。
装饰模式:是你还是你,一切拜托你(借用老崔经典词)。
它是由继承出现的,先有继承,再有装饰。
回忆继承
好处:提高复用性,让可以重复使用,通过方法重写利用后期扩展。
坏处:由于类与类之间的继承关系,但他们关系增强,耦性也就高了。不符合java宗旨:低耦合,高内聚。
对比如下:
a:
有一个Witer体系
|--TxtWrite
|--Mp3Write
|--DIDWrite
上面是一个普通子类实现,调用者觉得执行太慢,要求对三者进行增强(高效|缓冲)。修改如下
class myBuffereWrite exetends Write{
//接收子类:Fu f = new Zi();
private Write ziWrite;
public BuffereWrite(Write ziWrite)
{
this.ziWrite = ziWrite;
}
public void writeLine(String line)
{
//使用ziWrite进行整容处理,然后一行数据保存到write中。
}
public void close()
{
ziWrite.clese();//多态(调用的还是子类)!
}
public void flash(){
ziWrite.flash();//多态(调用的还是子类)!
}
....//重写Write的抽象方法,调用的myBuffereWrite中的,再方法里边调用是传送ziWrite。只不过在调用它
之前给它做了一些手术。
}
|--总结
1:比如你使用Write的高效功能,那你就创建myBuffereWrite,传递你的对其高效的对象,比如FileWrite();
2:装饰模式体现了对一个对象(功能)的增强(高内聚),然后紧密性比较弱(低耦合)。
3:JDK中用的装饰就挺多的,比如BufferedWriter(Writer out);PrintStream(OutputStream out);ObjectInputStream(InputStream in)等。
|--代码示例
模拟BuffereReader装饰类
package com.Decoration;
import java.io.IOException;
import java.io.Reader;
/**
* @author hubiao
* 模拟BuffereReader装饰类
*
* 分析:模拟一个类,就是自定一个类,实现它的特有方法:ReadLine();
* 1:模拟什么:特有方法
* 2:你有什么:根据装饰特点,自定的类继承一个抽象类,因为BuffereReader的readLine底层也是继承Reader中的。
* 我们要做的,也是继承Reader,写一个与BuffereReader一样的ReadLine方法来。
*/
public class MyBuffere extends Reader {
/*Reader是一个抽象类的父类,将需要高效的类都实现了它。都是它的子类。*/
private Reader reader = null;
public MyBuffere(Reader reader){
this.reader = reader;
}
public int read(char[] cbuf, int off, int len) throws IOException {
return reader.read(cbuf, off, len);
}
public String readLine() throws IOException
{
/**
* 1:这里要思考,使用
* A:read(char[] cbuf, int off, int len);一次读取一缓冲区
* B:read();//一次读取一个字符串
* 2:分析
* 我们模拟readLine目的是为了模拟什么?还不是为了实现BufferedReader中的readerLine一次读取一行的高效方法。
* 然后使用A方法不合适,因为它一次读取一个char容量定义的长度,我们封装好的代码很难获知调用者要读取的数据文本的每行数据有多长。
* 使用B方法的好处,是一次读取一个字符,当遇到
就说明是一行的结束,则说一行读取完毕,那怎么一行的数据每个字符用什么保存呢?
* 使用String, 这...太可怕了吧,因为我们知道String在java中是一个常量池。一但赋值,将不可变。所以选择效率高的StringBuilder
* 把每个字符拼接到StringBuffer中,再返回给调用者。
*/
//单字符容器
StringBuffer buffer = new StringBuffer();
//每个字符
int read = 0;
while((read = reader.read())!=-1)
{
char chr = (char) read;
if(chr=='
')
continue;
if(chr=='
')
return buffer.toString();
else
buffer.append(chr);
}
//防止读取的是最后一行,则没有
,那么再判断缓冲区中是否有值?如果有,则再返回。
if(buffer.length() > 0 )
return buffer.toString();
else
return null;
}
public void close() throws IOException {
reader.close();
}
}
模拟LineNumberReader
/**
* @author hubiao
* 模拟LineNumberReader
* 也是同样,模拟,就是自定一个类,模拟需求给出的特殊方法:获取每个行号,然后读取每一行。
*/
public class MyLineNumberReader extends Reader{
/*接收传递子类对象,Fu f = new Zi();//多态*/
private Reader reader;
private int lineNumber;//行号
public MyLineNumberReader(Reader reader) {
this.reader = reader;
}
public int read(char[] cbuf, int off, int len) throws IOException {
return reader.read(cbuf, off, len);
}
public String readLine() throws IOException
{
//单字符容器
StringBuffer buffer = new StringBuffer();
//每个字符
int read = 0;
while((read = reader.read())!=-1)//-1表示读取到流的结尾!
{
char chr = (char) read;
if(chr=='
')
continue;
if(chr=='
'){
lineNumber++;
return buffer.toString();
}
else
buffer.append(chr);
}
//防止读取的是最后一行,则没有
,那么再判断缓冲区中是否有值?如果有,则再返回。
if(buffer.length() > 0 ){
lineNumber++;
return buffer.toString();
}else
return null;
}
public void close() throws IOException {
reader.close();
}
public int getLineNumber() {
return lineNumber;
}
public void setLineNumber(int lineNumber) {
this.lineNumber = lineNumber;
}
}