装饰者模式讲解

package com.learn.design.pattern.structural.decorator.v1;/*** 我们现在创建一个煎饼类* 他有两个方法* * * @author Leon.Sun**/
public class Battercake {/*** 一个是获取描述getDesc* * 我们把它写成protected* 有的人喜欢在吃煎饼的时候加一个鸡蛋* 再加一根香肠* * * @return*/protected String getDesc(){return "煎饼";}/*** 还有一个方法cost* 他的价格消费多少* 假设这个煎饼8元* 现在商家创建一个煎饼类* 我在卖的时候可以卖一个煎饼* 我也可以卖加蛋的煎饼* 那我们再创建一个类* * * @return*/protected int cost(){return 8;}}
package com.learn.design.pattern.structural.decorator.v1;/*** 加蛋的煎饼* 继承了Battercake* 这里我们重写一下父类的方法* 因为权限在子类中重写* * * * @author Leon.Sun**/
public class BattercakeWithEgg extends Battercake {/*** 首先获取父类获得一个描述* 加上" 加一个鸡蛋"* * * * */@Overridepublic String getDesc() {return super.getDesc()+" 加一个鸡蛋";}/*** 价格也是* 煎饼卖8元* 加一个蛋加1块* 这个时候我们看一下* 对于权限的一个限制* 里面也说一下* * * */@Overridepublic int cost() {return super.cost()+1;}
}
package com.learn.design.pattern.structural.decorator.v1;/*** 这个类呢是加一个鸡蛋* 再加一根香肠* 我只需要让他继承加蛋的煎饼就可以了* 同理重写* 这两个方法* * * @author Leon.Sun**/
public class BattercakeWithEggSausage extends BattercakeWithEgg {/*** 他调用super之后呢* 他继续掉super* 加上后边" 加一根香肠"* * */@Overridepublic String getDesc() {return super.getDesc()+ " 加一根香肠";}/*** 香肠两块钱* 加2* 咱们写一个测试类* * */@Overridepublic int cost() {return super.cost()+2;}
}
package com.learn.design.pattern.structural.decorator.v1;/*** * @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 先new一个普通的* * */Battercake battercake = new Battercake();/*** 直接输出销售价格* 前面加上他的描述battercake.getDesc()* * */System.out.println(battercake.getDesc()+" 销售价格:"+battercake.cost());/*** battercakeWithEgg* * */Battercake battercakeWithEgg = new BattercakeWithEgg();System.out.println(battercakeWithEgg.getDesc()+" 销售价格:"+battercakeWithEgg.cost());/*** 加肠的也是同理* 这三个小伙伴都得到了满足* 吃了一个煎饼* 吃了一个加鸡蛋的煎饼* 也有一个加了鸡蛋加了香肠的煎饼* 这个时候又来了一个小伙伴* 我要吃一个煎饼* 加两个鸡蛋* 加两根香肠* 这个时候老板有点迷茫* 那我没有加两个鸡蛋加两根香肠的类* 那现在我这个系统算不出来* 这个应该卖多少钱的* 这个没有得到满足* 商家也没有挣到钱* 没有卖出去* 因为系统不支持* 那这个UML非常简单* * */Battercake battercakeWithEggSausage = new BattercakeWithEggSausage();System.out.println(battercakeWithEggSausage.getDesc()+" 销售价格:"+battercakeWithEggSausage.cost());}
}

package com.learn.design.pattern.structural.decorator.v2;/*** 前边加上abstract* 那这个方法我们直接拿过来* 前面要加上abstract* 因为在抽象类里面* 这两个方法要做成抽象方法* 那这个要被装饰的实体呢* 我们也要声明一个* 那就是实体煎饼* * * @author Leon.Sun**/
public abstract class ABattercake {protected abstract String getDesc();protected abstract int cost();}
package com.learn.design.pattern.structural.decorator.v2;/*** 他要继承ABattercake* 实现方法* 现在重要的装饰者就登场了* 首先我们让抽象的装饰者* 也继承这个抽象的实体* * * @author Leon.Sun**/
public class Battercake extends ABattercake {@Overrideprotected String getDesc() {return "煎饼";}@Overrideprotected int cost() {return 8;}
}
package com.learn.design.pattern.structural.decorator.v2;/*** 创建AbstractDecorator这个类* 他继承ABattercake这个抽象类* 然后实现里面的方法* 让AbstractDecorator来继承ABattercake* 很简单* 现在AbstractDecorator和实体的Battercake他们都是抽象类的子类* 那这个时候我们可以想象一下* 我如何让这两个子类建立关系呢* 我们可以通过它继承的父类* 来达到这个目的* * AbstractDecorator这个类现在并不是抽象类* 但是也能完成扩展的目的* 那为什么要加一层抽象的装饰者呢* 很简单* 我们来写一下* 现在把它改成抽象的类* 我们写个方法* * * * @author Leon.Sun**/
public abstract class AbstractDecorator extends ABattercake {/*** 我们让父类来声明一个ABattercake* 这个抽象的煎饼放到这里了* * */private ABattercake aBattercake;/*** 然后就是他的构造器* 通过构造器把这个抽象的煎饼放进来* 那现在我们看一下* 我们可以放抽象的煎饼进来* 就可以放实体的煎饼进来* 那这两个也非常简单* 因为我们已经把煎饼放进来了* 我们在调用这个抽象的装饰者的时候* 其实是把这个行为委托给抽象的煎饼来执行的* 这个时候我们就要实现实体的装饰者类* 我们有一个蛋装饰者* * * @param aBattercake*/public AbstractDecorator(ABattercake aBattercake) {this.aBattercake = aBattercake;}/*** 我们想象一下* 如果作为抽象的装饰者* 能够保证子类实现某个方法的话* 那么这个抽象的装饰者呢* 放到这里才会有意义* 所以这个类是不是抽象的类* 还要看具体的业务场景* 那在刚刚讲的这个场景当中呢* 他不是抽象的装饰者* 也是OK的* 因为并没有抽象方法* 新建的doSomething* 那如果我们创建了这个抽象方法* 那我们这个类应该是抽象类* 这样对于子类来说* 我们来看一下这个类* 是必须要实现doSomething方法的* * * */protected abstract void doSomething();@Overrideprotected String getDesc() {return this.aBattercake.getDesc();}@Overrideprotected int cost() {return this.aBattercake.cost();}
}
package com.learn.design.pattern.structural.decorator.v2;/*** EggDecorator这个类也是同理* * * @author Leon.Sun**/
public class EggDecorator extends AbstractDecorator {public EggDecorator(ABattercake aBattercake) {super(aBattercake);}/*** 那具体这个方法如何使用* 还是要看具体的业务场景* 例如老板在做煎饼* 加蛋的时候会有一个小动作* 又或者加肠的时候* 也有一些特定的小动作* 而这两个小动作呢* 分别属于各自的装饰者实现* 那这个时候对于两个实体的装饰者的父类* 用抽象的装饰者* 才会比较有意义* 具体最上层的装饰者* 是否使用装饰类* 要根据具体的业务场景* 这个呢并没有硬规定* 那我们再看一下图* * */@Overrideprotected void doSomething() {}/*** 描述写一下* " 加一个鸡蛋"* * */@Overrideprotected String getDesc() {return super.getDesc()+" 加一个鸡蛋";}/*** 一个鸡蛋一元钱* * */@Overrideprotected int cost() {return super.cost()+1;}
}
package com.learn.design.pattern.structural.decorator.v2;/*** 首先用香肠的实体装饰者类* 继承抽象的装饰者类* 然后实现这个默认的构造器* 那为什么要实现这个构造器呢* 很简单* 这个父类已经没有无参构造器了* 因为我们声明了一个有参构造器* 然后重写父类的这两个方法* 很简单* * * @author Leon.Sun**/
public class SausageDecorator extends AbstractDecorator{public SausageDecorator(ABattercake aBattercake) {super(aBattercake);}@Overrideprotected void doSomething() {}/*** " 加一根香肠"* * */@Overrideprotected String getDesc() {return super.getDesc()+" 加一根香肠";}/*** 香肠卖两元* * */@Overrideprotected int cost() {return super.cost()+2;}
}
package com.learn.design.pattern.structural.decorator.v2;/*** * @author Leon.Sun**/
public class Test {public static void main(String[] args) {/*** 我们声明一个抽象的煎饼* 刚刚说的第四个小伙伴来买这个煎饼* 老板给他做* 程序也能跑* 怎么跑呢* 看一下* * */ABattercake aBattercake;/*** 首先我们要给一个煎饼* new一个Battercake* * */aBattercake = new Battercake();/*** 这个时候注意* 他要两个鸡蛋* 我们用鸡蛋装饰者来包装一下这个煎饼* 然后呢* 再返回这个被包装的这个煎饼* 因为这个装饰者他继承抽象的装饰者* 而抽象的装饰者呢* 看一下UML* 他继承抽象的煎饼* 所以他的类型是可以被抽象的煎饼接收的* 同时我们注意UML里面的这个组合* 一个抽象的装饰者里面有一个抽象的煎饼* * * */aBattercake = new EggDecorator(aBattercake);/*** 这个时候小伙伴还需要一个鸡蛋* 那就加一个鸡蛋* * */aBattercake = new EggDecorator(aBattercake);/*** 然后这个小伙伴还是觉得有点饿* 加一根香肠* * */aBattercake = new SausageDecorator(aBattercake);/*** 这个时候我们就要打印一下* 老板煎饼也做完了* 价格从这个程序里跑了一下* 我们看一下结果* 煎饼* 加一个鸡蛋* 又加一个鸡蛋* 加一根香肠* 销售价格8元加1元加1元加两元* 12元* 那这样通过装饰者* 就把这个煎饼装饰出来了* 那现在讲到这里* 我们看一下前面悄悄地埋了一个伏笔* 我们看一下抽象的装饰者类* * */System.out.println(aBattercake.getDesc()+" 销售价格:"+aBattercake.cost());}
}
它是一个AbstractDecorator,那装饰者模式在实际的应用场景,也比较多,当然怎么用还是要看应用模型的,如果这个业务模型抽象可以的话,打个比方,假设有一个订单,而这个订单是一个旅行订单,旅行保险,我们想象一下,是否可以用保险装饰一下,和鸡蛋装饰煎饼是一样的,当然这个是需要看实际的业务模型,而且还有难度,那这里只是打个比方,那这个装饰者模式就讲到这里面

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部