什么是装饰者模式?
在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
重点理解一句话:动态的扩展一个对象的功能.
我理解的装饰者模式:把一个东西用另一个东西来包装一下,以增加这个东西本身的功能.
装饰者与继承的不同点.
Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
装饰者模式设计原则(了解):
1,多用组合,少用继承.
利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为.然而,如果有组合的做法扩展对象的行为,就可以运行进动态地进行扩展.
在前面提到策略模式中也提到了,多用组合.那么策略模式装饰者有什么不一样的呢?
1,装饰对象包含一个真实对象的引用,而策略模式里面持有的是同一类行为接口的引用.传入的时候是传入接口的实现类.
2,类设计应该对扩展开放,对修改关闭.
什么情况下要用装饰者模式.
要添增加一个类的功能的时候,不能改变这个类的代码.
javaIO典型的装饰者模式理解.
超类输入流:InputStream
两个分支:
1个是主体的分支.FileInputStrean,StringBufferInputString,ByteArrayInputStrean.
2,装饰者中间层,FilterInpuStrean
BufferInputStrean DataInputStream LineNumberInputStrean
现在我们要自己的扩展一个装饰者模式,大所有小写自动转成大写的流UpperCaseInputStream.
package com.java.jikexueyuan.myiodecorator; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; //直接继承分支的中间层. //因为分支的中间层已为我们设计好超类的引用 public class UpperCaseInputStream extends FilterInputStream{ //构造方法里面传入 protected UpperCaseInputStream(InputStream in) { //可以用super是因了,FilterInputStream是一个分支的中间层 super(in); } //写自己的方法 public int read() throws IOException { int c=super.read(); return c==-1?c:Character.toUpperCase((char)(c)); } public int read(byte[] b,int offset,int len) throws IOException { int result=super.read(b,offset,len); for(int i=0;i<result;i++) { b[i]=(byte)Character.toUpperCase((char)(b[i])); } return result; } }
记住一点,每一个分支都要有中间成.用在作为装饰者类里面的引用
装饰者模式怎么设计
1,有一个抽象的超类,里面有抽象的方法,和一些共有属性字段信息.
2,然后就是主体部分,主体部分可以理解成抽象超类的子类.主体类可以有一个中间层.
//这是那个超类 public abstract class Animal { //这是共有属性 public String language; //get/set //共有的方法 public abstract String Speak(); } //这个类就是那个中间层(这一层也可以省略) public class Human extends Animal { @Override public String Speak() { return super.language; } } //这是主体分支,就是超类的子类.当然还可以扩展出很子类出来.只举一个例子. public class Chinese extends Human { public Chinese(){ super.language="汉语"; } //这里是可以直接继承了Human类的Speak方法的.就要以不用在写了 }
下面才是真正的装饰者的部分:
1,同样要有一个中间层,(重点),主要就是这个中间层的设计.
2,直接分支--直接改写方法,或添加方法.
3,中间层这个类里面有一个超类的引用,通过构造方法传入(重点).
中间层类直接 继承超类,里面有一个超类的引用从构造方法传入.
然后就是一些自己的方法.
要装饰的类直接继承这个中间者类.
//功夫就是这个中间成. public class Gongfu extends Animal{ Animal animal; Gongfu(Animal animal) { this.animal=animal; } public void gongfu(){ System.out.println("这个人会功夫"); } 是间层里面不用改变的方法直接调用父类来返回 @Override public String Speak() { return animal.Speak(); } } //用功夫来装饰一个人 public class Taiji extends Gongfu { //这个会自动生成,因为Gongfu没有无参的构造方法 Taiji(Animal animal) { super(animal); } public void taiji(){ System.out.println("这个人会taiji"); } }
这个代码有一点问题,没有时间去思考了.但是装饰者的大体思想这样.