写点什么

DecoratorPattern- 装饰者模式

作者:梁歪歪 ♚
  • 2022 年 5 月 29 日
  • 本文字数:2145 字

    阅读完需:约 7 分钟

DecoratorPattern-装饰者模式

装饰者模式

装饰者模式(Decorator Pattern):是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案来扩展原有对象的功能,装饰者模式属于结构型模式。


示例:我们以生活中的蛋糕来举例说明。


  • 蛋糕的抽象类Cake.java


package cn.liangyy.decorator;
import java.math.BigDecimal;
/** * 蛋糕类 */public abstract class Cake { /** * 获取蛋糕的基本信息 * @return */ public abstract String getCakeMsg();
/** * 获取蛋糕的价格 * @return */ public abstract BigDecimal getPrice();}
复制代码


  • 原生蛋糕BaseCake.java


package cn.liangyy.decorator;
import java.math.BigDecimal;
/** * 原生蛋糕类(纯奶油蛋糕) */public class BaseCake extends Cake {
/** * 获取蛋糕的基本信息 * * @return */ @Override public String getCakeMsg() { return "我是一个蛋糕"; }
/** * 获取蛋糕的价格 * * @return */ @Override public BigDecimal getPrice() { return new BigDecimal("68"); }}
复制代码


  • 抽象装饰器CakeDecorator.java


package cn.liangyy.decorator;
import java.math.BigDecimal;
/** * 抽象装饰器 */public abstract class CakeDecorator extends Cake { private Cake cake;
public CakeDecorator(Cake cake){ this.cake = cake; }
/** * 获取蛋糕的基本信息 * * @return */ @Override public String getCakeMsg() { //调用被装饰的对象原生方法 return this.cake.getCakeMsg(); }
/** * 获取蛋糕的价格 * * @return */ @Override public BigDecimal getPrice() { //调用被装饰的对象原生方法 return this.cake.getPrice(); }}
复制代码


  • 芒果装饰器类CakeAddMangoDecorator.java


package cn.liangyy.decorator;
import java.math.BigDecimal;
/** * 芒果装饰器 */public class CakeAddMangoDecorator extends CakeDecorator { public CakeAddMangoDecorator(Cake cake) { super(cake); }
/** * 获取蛋糕的基本信息 * * @return */ @Override public String getCakeMsg() { return super.getCakeMsg()+"一个芒果"; }
/** * 获取蛋糕的价格 * * @return */ @Override public BigDecimal getPrice() { return super.getPrice().add(new BigDecimal("8")); }}
复制代码


  • 葡萄装饰器类CakeAddGrapeDecorator.java


package cn.liangyy.decorator;
import java.math.BigDecimal;
/** * 葡萄装饰器类 */public class CakeAddGrapeDecorator extends CakeDecorator { public CakeAddGrapeDecorator(Cake cake) { super(cake); }
/** * 获取蛋糕的基本信息 * * @return */ @Override public String getCakeMsg() { //调用父类装饰器方法,再加上自定义的装饰 return super.getCakeMsg()+"1个葡萄"; }
/** * 获取蛋糕的价格 * * @return */ @Override public BigDecimal getPrice() { //调用父类装饰器方法,再加上自定义的装饰 return super.getPrice().add(new BigDecimal("5")); }}
复制代码


  • 测试


package cn.liangyy.decorator;
/** * 装饰者模式-测试 */public class TestCakeDecorator { public static void main(String[] args) { Cake cake = null; //普通蛋糕 cake = new BaseCake(); System.out.println(cake.getCakeMsg()+",价格 "+cake.getPrice()); //加一个芒果 cake = new CakeAddMangoDecorator(cake); System.out.println(cake.getCakeMsg()+",价格 "+cake.getPrice()); //加一个葡萄 cake = new CakeAddGrapeDecorator(cake); System.out.println(cake.getCakeMsg()+",价格 "+cake.getPrice()); //再加一个芒果 cake = new CakeAddMangoDecorator(cake); System.out.println(cake.getCakeMsg()+",价格 "+cake.getPrice()); }}
复制代码



可以看到,在使用装饰者模式之后,扩展之前的功能变得极为方便,可以根据现有的装饰器进行任意组合,而如果现有装饰器无法满足也可以新建装饰器来完成功能的扩展,依然十分方便。


装饰者模式使用场景


  • 装饰者模式能将代理对象与真实被调用的目标对象分离,降低了系统的耦合度,所以扩展性比较好。

  • 动态的给一个对象添加功能时非常方便,而且还支持随时撤销这些添加的功能。


装饰者模式优点


  • 装饰者比继承更加灵活,可以在不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。

  • 通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。

  • 新增装饰者模式时,只需要新增对应的装饰者类,无需修改源码,符合开闭原则。


装饰器模式缺点当装饰者非常多的时候,会引起类膨胀,使得系统更加复杂难以维护。

发布于: 刚刚阅读数: 5
用户头像

梁歪歪 ♚

关注

还未添加个人签名 2021.07.22 加入

还未添加个人简介

评论

发布
暂无评论
DecoratorPattern-装饰者模式_设计模式_梁歪歪 ♚_InfoQ写作社区