一、装饰设计模式:
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有功能,提供加强功能。
那么自定义的类称为装饰类。
例子:对人吃饭这一功能进行增强
class Person
{
public void eat()
{
System.out.println("吃饭");
}
}
class SuperPerson
{
private Person p;
SuperPerson(Person p)
{
this.p = p;
}
public void supereat()
{
System.out.println("开胃酒");
p.eat();
System.out.println("甜点");
System.out.println("来根烟");
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
SuperPerson sp=new SuperPerson(p);
sp.supereat();
}
}
由该例可知,装饰类通常会通过构造方法接受被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
二、装饰与继承的区别:
MyReader//专门用于读取数据的类。
|——MyTextReader
|——MyBufferTextReader
|——MyMediaReader
|——MyBufferMediaReader
|——MyDataReader
|——MyBufferDataReader
class MyBufferReader
{
MyBufferReader(MyTextReader text)
{}
MyBufferReader(MyMediaReader medi)
{}
}
上面这个类扩展性很差。
找到其参数的共同类型,通过多态的形式,可以提高扩展性。
class MyBufferReader extends MyReader
{
MyBufferReader (MyReader r)
{}
}
MyReader//专门用于读取数据的类。
|——MyTextReader
|——MyMediaReader
|——MyDataReader
|——MyBufferDataReader
装饰模式比继承要灵活,避免了继承体系的臃肿,而且降低了类与类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常是都属于一个体系的。
三、IO中的装饰设计模式:
例子:模拟一个带行号的缓冲区对象。
class MyLineNumberReader
{
private Reader r;
private int lineNumber;
MyLineNumberReader(Reader r)
{
this.r = r;
}
public String myReadLine() throws Exception
{
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = r.read())!=-1)
{
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
public void setLineNumber(int lineNumber)
{
this.lineNumber = lineNumber;
}
public int getLineNumber()
{
return lineNumber;
}
public void myClose()throws IOException
{
r.close();
}
}
class MyLineNumberReaderDemo
{
public static void main(String[] args)throws Exception
{
FileReader fr = new FileReader("123.java");
MyLineNumberReader mylnr = new MyLineNumberReader(fr);
String line = null;
while((line=mylnr.myReadLine())!=null)
{
System.out.println(line);
}
mylnr.myClose();
}
}
装饰设计模式解决:对一组类进行功能的增强。
包装:写一个类(包装类)对被包装对象进行包装;
1、包装类和被包装对象要实现同样的接口;
2、包装类要持有一个被包装对象;
3、包装类在实现接口时,大部分方法是靠调用被包装对象来实现的,对于需要修改的方法我们自己实现