装饰器模式
装饰模式定义:在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象,装饰器模式要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例,并且装饰对象也可以被其它的装饰对象继续装饰。
拿普通人、军人和高富帅举个例子,普通人可以被装饰为军人、高富帅和高富帅军人。来看类图:
装饰器模式中有四种角色
1、被装饰父类接口:本例中的Person接口,它可以是一个抽象类,甚至是一个普通类(普通的类作为继承体系的超级父类不易于维护,所以一般不会这样做)
2、被装饰类:本例中的NormalPerson,它实现Person接口
3、装饰类基类:本例中的SepPenson是一个装饰类的基类,他持有Penson的实例,同时实现Person接口,这个角色不是必须的
4、具体装饰类:本例中的军人和高富帅
java版demo如下:
package Decorator; public interface Person { void eat(); }
package Decorator; public class NormalPerson implements Person { @Override public void eat() { System.out.println("吃饭"); } }
package Decorator; public class SepPerson implements Person { Person person; public SepPerson(Person person) { super(); this.person = person; } @Override public void eat() { person.eat(); } }
package Decorator; public class Soldier extends SepPerson { public Soldier(Person person) { super(person); } public void fight() { System.out.println("打仗"); } public void eat() { System.out.println("唱国歌"); super.eat(); } }
package Decorator; public class Gfs extends SepPerson { public Gfs(Person person) { super(person); } public void paoniu() { System.out.println("泡妞"); } public void eat() { System.out.println("洗手"); super.eat(); System.out.println("擦嘴"); } }
简单写一个测试类
package Decorator; public class Client { public static void main(String[] args) { Person person = new NormalPerson(); person.eat(); System.out.println("-------------------"); Soldier soldier = new Soldier(person); soldier.fight(); soldier.eat(); System.out.println("-------------------"); Gfs gfs = new Gfs(person); gfs.paoniu(); gfs.eat(); System.out.println("-------------------"); Gfs gfs2 = new Gfs(soldier); gfs2.paoniu(); gfs2.eat(); } }
执行结果如下
在测试中,我们先将NormalPerson装饰为军人,然后又装饰为高富帅,最后又将军人装饰为高富帅。熟悉io操作的同学可能对这样的代码很熟悉:
InputStream inputStream = new FileInputStream(filePath); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); DataInputStream dataInputStream = new DataInputStream(bufferedInputStream)
java中io流的类为什么要这么设计呢?其实就是使用了装饰器模式,真正执行读写文件的只有FileInputStream和FileOutputStream,通过装饰器模式不断的扩展其功能才有了让我们可以更方便的读写文件的各种流,这里贴上网上找的io流的类图,各位可以自行和上面的标准装饰器模式对比一下,或者去查看源码也可以。
图中左半部分是字节流,右边是字符流,中间通过一个InputStreamReader来作为桥梁。