装饰者模式(Decorator Pattern):装饰者模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个装饰对象,来包裹真实的对象,即被装饰对象。
稍微百度一下,看到都是乱七八糟的文章。。这里,我用举例子的方法来给介绍装饰者模式。
从实际出发,把生活中的例子活用到代码中能更好地理解。比如说,工人有很多种,水管工、木匠之类的,不同的职业也有分不同的公司的,A公司、B公司等等。下面我弄了一个图来说明工人、具体工种、不同工种在不同公司之间的关系:
同时,也抛出了一个疑问,这些层次关系要怎么表示,该用继承吗?当然可以用继承,但是有一个问题,假如还有很多别的工种呢?还有很多别的公司呢?如果每间公司都有所有的工种,那么,一共需要的类太多了吧,这样会造成所谓的“类爆炸”。因此,我们用装饰者模式来解决这个问题。
1.新建一个公共接口Worker
1 //新建一个Worker接口 2 interface Worker{ 3 public void doSomeWork(); 4 }
2.添加各种职业,实现Worker接口
//新建一个Plunmber类,实现Worker接口 class Plumber implements Worker{ public void doSomeWork(){ System.out.println("修水管"); } } //新建一个Carpenter类,实现Worker接口 class Carpenter implements Worker{ public void doSomeWork(){ System.out.println("修门窗"); } }
3.添加公司,实现Worker接口,该部分体现装饰者模式的核心。
1 //新建一个AWorker类,实现Worker接口 2 class AWorker implements Worker{ 3 private Worker worker; 4 public AWorker(Worker worker){ 5 this.worker = worker; 6 } 7 public void doSomeWork(){ 8 System.out.println("你好"); //A公司对员工的要求 9 worker.doSomeWork(); 10 } 11 } 12 13 //新建一个BWorker类,实现Worker接口 14 class BWorker implements Worker{ 15 private Worker worker; 16 public BWorker(Worker worker){ 17 this.worker = worker; 18 } 19 public void doSomeWork(){ 20 System.out.println("进门前穿鞋套"); //B公司对员工的要求 21 worker.doSomeWork(); 22 } 23 }
4.写一个Demo来测试装饰者模式
1 public class Decorator 2 { 3 public static void main(String[] args) 4 { 5 //实例化一个Plumber对象,隶属于A公司 6 Plumber plumber = new Plumber(); 7 AWorker aWorker = new AWorker(plumber); 8 aWorker.doSomeWork(); 9 10 //实例化一个Carpenter对象,隶属于B公司 11 Carpenter carpenter = new Carpenter(); 12 BWorker bWorker = new BWorker(carpenter); 13 bWorker.doSomeWork(); 14 } 15 }
运行结果如下:
分析:结合本文一开始的介绍,AWorker和BWorker其实就是装饰者,而Plumber和Carpenter是被装饰者,即真实需要的对象,而因为Worker接口是Plumber和Carpenter的父类,根据多态性原理,传值成功,在装饰者对象的doSomeWork()方法中,worker.doSomeWork()方法会根据装饰者对象在实例化过程中的具体参数而调用对应的被装饰者的doSomeWork()方法。装饰者模式的特征就是:被装饰者类(装饰者类 装饰者对象)。
总结:装饰者模式的好处就是省略了众多繁琐的类之间的继承,用这种方法比用继承要更加灵活。当有新的类加入时,不需要让下层的其他类来继承这个新的类,只需要让这个新的类实现顶层的接口就可以了。当然这是它的优点之一,这个模式也有不足之处,当已存在的类需要改变时,也只能老老实实地找出那个类然后修改了。