08_装饰者模式
【装饰者模式】
动态的给一个对象的添加一些额外的职责,就增加功能而言,装饰模式比直接继承的子类会更加灵活。
装饰模式由4部分组成
1.Component抽象构件(ISoldier接口)
2.ConcreteComponent具体构件(Soldier类)
3.Decorator装饰者类(AbstractRMBSoldier抽象类)
4.ConcreteDecorator具体装饰者类 (RMBSoldier类)
【装饰者模式 例子】
package com.Higgin.Decorator; import java.util.Random; /** * 战士接口 */ interface ISoldier{ public void shoot(); } /** * 具体普通战士类 */ class Soldier implements ISoldier{ @Override public void shoot() { System.out.println("战士举枪,射击!!!"); } } /** * 人民币玩家的 抽象战士类 */ abstract class AbstractRMBSoldier implements ISoldier{ protected ISoldier soldier=null; public AbstractRMBSoldier(ISoldier soldier){ this.soldier=soldier; } @Override public void shoot() { this.soldier.shoot(); } } /** * 人民币玩家的 具体战士类 */ class RMBSoldier extends AbstractRMBSoldier{ public RMBSoldier(ISoldier soldier) { super(soldier); } public void beforeShoot(){ System.out.println("战士戴上头盔..."); System.out.println("战士穿上防弹衣..."); System.out.println("战士给枪装上消音器..."); } public void afterShoot(){ System.out.println("射击结束,再扔个手雷..."); } @Override public void shoot() { this.beforeShoot(); this.soldier.shoot(); this.afterShoot(); } } /** * 装饰器测试 */ public class TestDecorator { public static void main(String[] args) { ISoldier soldier=new Soldier(); ISoldier rmbSoldier=new RMBSoldier(soldier); rmbSoldier.shoot(); } }
【运行结果】
【装饰者模式 优点】
* 装饰者和被装饰者可以独立发展,而不会相互耦合。
* 装饰者模式是继承的一个替代方案。
* 装饰者模式也可以动态地扩展一个类的实现类。
【装饰者模式 缺点】
多层装饰较为复杂。
【装饰者模式 使用场景】
* 需要动态扩展一个类的实现类,或者给类添加一个附加功能。
* 需要动态地给一个对象增加功能,这些功能也可以动态地撤销。
* 需要为一批的兄弟类进行改装或加装功能,首选装饰器模式。
【注意:装饰者模式与代理模式的区别】
发现装饰者模式和静态代理模式UML图一模一样!!!为什么还要区分这两个模式呢?
装饰者模式:注重对被装饰者的方法的增强,比如本例中的装饰者(RMBSoldier类)对被装饰者(Soldier类)的shoot方法进行了增强,本质上,被装饰类的shoot方法还是会执行的,只是增强了。
代理模式:注重对被代理类的方法的控制,比如我们代理类(RMBSoldier类)对代理者(Soldier类)的shoot方法,可以 这样改:
/** * 人民币玩家的 具体战士类 */ class RMBSoldier extends AbstractRMBSoldier{ public RMBSoldier(ISoldier soldier) { super(soldier); } public void beforeShoot(){ System.out.println("战士戴上头盔..."); System.out.println("战士穿上防弹衣..."); System.out.println("战士给枪装上消音器..."); } public void afterShoot(){ System.out.println("射击结束,再扔个手雷..."); } @Override public void shoot() { Random r=new Random(); if(r.nextBoolean()){ //随机生成一个Boolean类型的数据 this.beforeShoot(); this.soldier.shoot();//被代理的类的方法,有可能执行,也有可能不执行!!! this.afterShoot(); }else{ System.out.println("老子不爽,不射击了!"); } } }