声明:
本博客是本人在学习《Java 设计模式精讲》后整理的笔记,旨在方便复习和回顾,并非用作商业用途。
本博客已标明出处,如有侵权请告知,马上删除。
1. 装饰者模式讲解
- 定义:在不改变原有对象的基础之上,将功能附加到对象上。
- 提供了比继承更有弹性的替代方案(扩展原有对象功能)
- 类型:结构型
- 扩展一个类的功能或给一个类添加附加职责
- 动态的给一个对象添加功能,这些功能可以再动态的撤销
- 优点
- 继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能
- 通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果
- 符合开闭原则
- 缺点
- 会出现更多的代码,更多的类,增加程序复杂性
- 动态装饰时,多层装饰时会更复杂
- 相关设计模式
- 装饰者模式和代理模式
- 装饰者模式关注在一个对象上动态的添加方法
- 代理模式关注于控制对对象的访问,代理类可以对它的客户隐藏一个对象的具体信息
- 通常我们在使用代理模式的时候,常常在一个代理类中创建一个类的实例,而当我们使用装饰者模式的时候,我们通常会将原始对象作为一个参数传给装饰者的构造器
- 装饰者模式和适配器模式
- 装饰者模式和适配器模式都可以被称作包装模式
- 装饰者和被装饰者可以实现相同的接口,或者装饰者是被装饰者的子类
- 适配器和被适配类具有不同的接口
- 装饰者模式和代理模式
2. 装饰者模式 Coding
现在我们模拟一个卖煎饼的业务场景:
-
创建煎饼类
public class Battercake { protected String getDesc() { return "煎饼"; } protected int cost() { return 8; } }
-
创建煎饼加鸡蛋类
public class BattercakeWithEgg extends Battercake { @Override public String getDesc() { return super.getDesc()+"加一个鸡蛋"; } @Override public int cost() { return super.cost()+1; } }
-
创建煎饼加鸡蛋加香肠类
public class BattercakeWithEggSausage extends BattercakeWithEgg{ @Override public String getDesc() { return super.getDesc()+"加一个香肠"; } @Override public int cost() { return super.cost()+2; } }
-
测试类
public class Test { public static void main(String[]args){ Battercake battercake = new Battercake(); System.out.println(battercake.getDesc()+"销售价格:"+battercake.cost()); BattercakeWithEgg battercakeWithEgg = new BattercakeWithEgg(); System.out.println(battercakeWithEgg.getDesc()+"销售价格:"+battercakeWithEgg.cost()); BattercakeWithEggSausage battercakeWithEggSausage = new BattercakeWithEggSausage(); System.out.println(battercakeWithEggSausage.getDesc()+"销售价格:"+battercakeWithEggSausage.cost()); } }
运行结果:
煎饼销售价格:8 煎饼加一个鸡蛋销售价格:9 煎饼加一个鸡蛋加一个香肠销售价格:11
如果有人要加两个鸡蛋,那么我们又要创建一个煎饼加两个鸡蛋类,通过继承的方式拓展性非常差。
下面我们使用装饰者模式:
-
创建抽象煎饼类
public abstract class ABattercake { protected abstract String getDesc(); protected abstract int cost(); }
-
创建煎饼类继承于抽象兼饼类
public class Battercate extends ABattercake { @Override protected String getDesc() { return "煎饼"; } @Override protected int cost() { return 8; } }
-
创建抽象的装饰者类继承抽象的实体
public class AbstractDecorator extends ABattercake{ private ABattercake aBattercake; public AbstractDecorator(ABattercake aBattercake) { this.aBattercake = aBattercake; } @Override protected String getDesc() { return aBattercake.getDesc(); } @Override protected int cost() { return aBattercake.cost(); } }
-
煎饼添加鸡蛋的装饰类继承于抽象的装饰类
public class EggDecorator extends AbstractDecorator { public EggDecorator(ABattercake aBattercake) { super(aBattercake); } @Override protected String getDesc() { return super.getDesc() + "加一个鸡蛋"; } @Override protected int cost() { return super.cost() + 1; } }
-
煎饼添加香肠的装饰类继承于抽象的装饰类
public class SausageDecorator extends AbstractDecorator { public SausageDecorator(ABattercake aBattercake) { super(aBattercake); } @Override protected String getDesc() { return super.getDesc() + "加一根香肠"; } @Override protected int cost() { return super.cost() + 2; } }
-
测试类,要一个加两个鸡蛋一个香肠的煎饼
public class Test { public static void main(String[] args) { ABattercake aBattercake = new Battercate(); aBattercake = new EggDecorator(aBattercake); aBattercake = new EggDecorator(aBattercake); aBattercake = new SausageDecorator(aBattercake); System.out.println(aBattercake.getDesc() + " 价格:"+aBattercake.cost()); } }
运行结果:
煎饼加一个鸡蛋加一个鸡蛋加一根香肠 价格:12
现在类图如下所示: