900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 手抓饼加生菜加鸡蛋的装饰器模式

手抓饼加生菜加鸡蛋的装饰器模式

时间:2024-03-31 22:03:44

相关推荐

手抓饼加生菜加鸡蛋的装饰器模式

装饰器模式

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

装饰器模式的核心是功能扩展。使用装饰器可以透明且动态地扩展类的功能。

下面是通用的UML类图:

生活中的应用场景

看完上面的概念以及类图可能比较抽象,接下来我会举一个生活中的场景,来通俗易懂的讲解装饰器模式。

我们在早上上班途中,往往会在公司门口买一个手抓饼,然后带到工位上慢慢吃,相信很多小伙伴有过类似的经历。那么一个手抓饼什么都不加就是五块钱,我们把这个叫做标配,当然也可以按照你的喜好做一些定制化的需求,加里脊,加生菜,加培根等等,全凭个人的喜好来,这个过程就是一个装饰器模式。

下面我们用代码还原一下码农的生活。首先创建一个手抓饼的抽象Pancake类:

/*** @author jackxu*/public abstract class Pancake {protected abstract String getMsg();protected abstract int getPrice();}

创建一个基本的手抓饼类BasePancake,我们把这个叫做标配,就是什么都不加的五块钱一个

/*** @author jackxu*/public class BasePancake extends Pancake {@Overrideprotected String getMsg() {return "标配手抓饼";}@Overridepublic int getPrice() {return 5;}}

然后再创建一个扩展手抓饼的抽象装饰器PancakeDecorator类:

/*** @author jackxu*/public class PancakeDecorator extends Pancake {private Pancake pancake;public PancakeDecorator(Pancake pancake) {this.pancake = pancake;}@Overrideprotected String getMsg() {return this.pancake.getMsg();}@Overridepublic int getPrice() {return this.pancake.getPrice();}}

创建一个继承自抽象装饰器类的生菜装饰器LettuceDecorator类:

/*** @author jackxu*/public class LettuceDecorator extends PancakeDecorator {public LettuceDecorator(Pancake pancake) {super(pancake);}@Overrideprotected String getMsg() {return super.getMsg() + "+1片生菜";}@Overridepublic int getPrice() {return super.getPrice() + 1;}}

同理创建一个鸡蛋装饰器EggDecorator类:

/*** @author jackxu*/public class EggDecorator extends PancakeDecorator {public EggDecorator(Pancake pancake) {super(pancake);}@Overrideprotected String getMsg() {return super.getMsg() + "+1个鸡蛋";}@Overridepublic int getPrice() {return super.getPrice() + 1;}}

好,现在所有的类都已经写完了,让我们写个测试用例来测试一下:

/*** @author xhj* @date /2/23 16:45*/public class Test {public static void main(String[] args) {//A同学买了一个标配Pancake pancake = new BasePancake();System.out.println("A同学买了一个" + pancake.getMsg() + ",总价是" + pancake.getPrice() + "元");//B同学买了加鸡蛋的手抓饼Pancake pancakeWithEgg = new EggDecorator(pancake);System.out.println("B同学买了一个" + pancakeWithEgg.getMsg() + ",总价是" + pancakeWithEgg.getPrice() + "元");//C同学买了加生菜的手抓饼Pancake pancakeWithLettuce = new LettuceDecorator(pancake);System.out.println("C同学买了一个" + pancakeWithLettuce.getMsg() + ",总价是" + pancakeWithLettuce.getPrice() + "元");//D同学买了加鸡蛋加生菜的手抓饼Pancake pancakeWithEggAndLettuce = new LettuceDecorator(pancakeWithEgg);System.out.println("D同学买了一个" + pancakeWithEggAndLettuce.getMsg() + ",总价是" + pancakeWithEggAndLettuce.getPrice() + "元");}}

运行结果:

怎样,与我们预期希望看到的结果相符吧,我们用代码还原了现实生活中的一个场景。标配还是那个标配,对于别的需求,我们可以通过层层包装、装饰来实现很多的排列组合,而不是通过继承的方式,为每一种情况都生成一个类,那这样就会产生很多的类,这就是装饰器巧妙、灵活的地方。

最后让我们看下这几个类的UML类图:

和上面通用的类图长的一样吧,这里的PancakeDecorator抽象装饰器是非必需的,如果装饰器多的话我们可以抽象一个出来,如果装饰器单一的话,就可以省略该类,直接继承Pancake实现一个具体装饰器即可。

源码中的应用场景

当我在学习mybatis里面的一级缓存和二级缓存的时候,我看它的源码,发现在cache包下面有一个熟悉的单词,那就是decorators,这个就是装饰的意思,我大胆的猜测它用的就是装饰器模式。

查看了一下引用,发现一段似曾相识的代码,原来decorators包下的每一个类都是装饰类,这里面将cache层层的包装,达到对缓存作用增强的功能。

具体增强的功能如下:

装饰器模式的优缺点

优点:

装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。装饰器完全遵守开闭原则。

缺点:会出现更多的代码,更多的类,增加程序复杂性。动态装饰时,多层装饰会更复杂。

源码

/xuhaoj/pattern-demo ,其他设计模式的例子也在该项目中,谢谢大家的观看。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。