装饰者模式(Decorator Pattern):装饰者模式是在没必要改变原类文件和使用继承的状况下,动态地扩展一个对象的功能。它是经过建立一个装饰对象,来包裹真实的对象,即被装饰对象。测试
稍微百度一下,看到都是乱七八糟的文章。。这里,我用举例子的方法来给介绍装饰者模式。this
从实际出发,把生活中的例子活用到代码中能更好地理解。好比说,工人有不少种,水管工、木匠之类的,不一样的职业也有分不一样的公司的,A公司、B公司等等。下面我弄了一个图来讲明工人、具体工种、不一样工种在不一样公司之间的关系:spa
同时,也抛出了一个疑问,这些层次关系要怎么表示,该用继承吗?固然能够用继承,可是有一个问题,假如还有不少别的工种呢?还有不少别的公司呢?若是每间公司都有全部的工种,那么,一共须要的类太多了吧,这样会形成所谓的“类爆炸”。所以,咱们用装饰者模式来解决这个问题。code
1.新建一个公共接口Worker对象
1 //新建一个Worker接口 2 interface Worker{ 3 public void doSomeWork(); 4 }
2.添加各类职业,实现Worker接口blog
//新建一个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 }
运行结果以下:class
分析:结合本文一开始的介绍,AWorker和BWorker其实就是装饰者,而Plumber和Carpenter是被装饰者,即真实须要的对象,而由于Worker接口是Plumber和Carpenter的父类,根据多态性原理,传值成功,在装饰者对象的doSomeWork()方法中,worker.doSomeWork()方法会根据装饰者对象在实例化过程当中的具体参数而调用对应的被装饰者的doSomeWork()方法。装饰者模式的特征就是:被装饰者类(装饰者类 装饰者对象)。原理
总结:装饰者模式的好处就是省略了众多繁琐的类之间的继承,用这种方法比用继承要更加灵活。当有新的类加入时,不须要让下层的其余类来继承这个新的类,只须要让这个新的类实现顶层的接口就能够了。固然这是它的优势之一,这个模式也有不足之处,当已存在的类须要改变时,也只能老老实实地找出那个类而后修改了。