小言_互联网的博客

Java结构型设计模式 —— 用装饰者模式来卖煎饼果子

409人阅读  评论(0)

一、引言

9月30号上映,《我和我的祖国》这个电影,小编不知道你们看了没,还挺不错的。

其中讲述了新中国成立、中国女排、香港回归、首颗原子弹爆炸等等历史性的事件,小编再一次体会到中国的强大。

国庆节假期现在是第四天了,去年这个时候小编还记得再写redis相关操作,年复一年。

二、装饰者定义

结构型设计模式,动态的将新功能附加到对象上,在对象功能扩展方面,他比继承更加有弹性,装饰者模式也体现了开闭原则。

那装饰者有什么优点呢? 可能刚一开始说还看不太明白,看完具体案例分析实现,再回头来看,是否理解。

1、扩展一个类的功能,或者给一个类增加附加职责。

2、通过这些不同的装饰者,可以使被装饰者实现不同的效果。

3、符合开闭原则,可以在不改变原有类的情况下,给个对象添加新的功能。

三、装饰者案例分析

你们喜欢吃手抓饼嘛? 

小编吃手抓饼喜欢加培根肉松,再外加一瓶牛奶,完美解决早餐。

那就以这个生活为案例,假设现在有一款手抓饼的产品,可以加多份不同的配料,然后计算最后的价格。

小伙伴们可以先想想,如果要你现在设计这么一个功能,你会怎么去设计?

注意:一个手抓饼可以加两份培根,一份肉松等等,还需要注意程序的可扩展性、维护性。

装饰者就比较适合这种场景来使用,下面进行角色分析

1、抽象产品:被装饰者基类,用来定义被装饰者的行为和方法

2、被装饰者:具体的装饰者类,可以动态添加新的功能(比如一个手抓饼可以加鸡蛋、火腿等等)。

3、抽象装饰者:需要聚合或者组合具体被装饰者,还需要继承或者实现抽象产品

4、装饰者:持有被装饰者对象,并且进行新功能的添加

四、装饰者案例实现

步骤一:首先我们需要创建产品,产品是主要内容,装饰是其次(首先你要有煎饼果子可以卖,才可以加火腿之类的)。

/**
 * @Auther: IT贱男
 * @Date: 2019/8/21 13:54
 * @Description: 产品抽象类
 */
public interface Apancake {

    /**
     * 产品描述
     * @return
     */
    String getDesc();

    /**
     * 产品价格
     * @return
     */
    int cost();

}

/**
 * @Auther: IT贱男
 * @Date: 2019/8/21 13:56
 * @Description: 被装饰者 - 煎饼果子
 */
public class BatterCake implements Apancake {

    @Override
    public String getDesc() {
        return "煎饼果子";
    }

    @Override
    public int cost() {
        return 5;
    }
}

步骤二:现在具体产品有了,那么光一个煎饼果子也不够吃呀,商家还提供了可以加火腿、鸡蛋这个配料。

/**
 * @Auther: IT贱男
 * @Date: 2019/8/21 13:57
 * @Description: 抽象装饰者 - 实现产品接口
 */
public class AbstractDecorate implements Apancake {

    // 聚合一个具体的被装饰者
    protected Apancake apancake;

    public AbstractDecorate(Apancake apancake) {
        this.apancake = apancake;
    }

    @Override
    public String getDesc() {
        // 调用被装饰者的方法
        return this.apancake.getDesc();
    }

    @Override
    public int cost() {
        // 调用被装饰者的方法
        return this.apancake.cost();
    }
}
/**
 * @Auther: IT贱男
 * @Date: 2019/8/21 14:02
 * @Description: 火腿肠装饰者 -> 继承抽象抽象装饰者
 */
public class SausageDecorate extends AbstractDecorate {

    public SausageDecorate(Apancake apancake) {
        super(apancake);
    }

    @Override
    public String getDesc() {
        // 首先需要调用父类的方法,获取原本结果的基础之上,新增新功能
        return super.getDesc() + "加一个火腿肠加两元";
    }

    @Override
    public int cost() {
        // 首先需要调用父类的方法,获取原本的价格,加一根火腿的价格
        return super.cost() + 2;
    }
}
/**
 * @Auther: IT贱男
 * @Date: 2019/8/21 13:59
 * @Description: 鸡蛋装饰者 -> 继承抽象抽象装饰者
 */
public class EggDecorate extends AbstractDecorate {

    public EggDecorate(Apancake apancake) {
        super(apancake);
    }

    @Override
    public String getDesc() {
        return super.getDesc() + "加一个鸡蛋一元";
    }

    @Override
    public int cost() {
        return super.cost() + 1;
    }
}

步骤三:测试,现在来了一个客人,需要一个加鸡蛋、火腿的煎饼果子。 原本只是一个普通的煎饼果子,经过装饰者这么一操作之后,就变得不普通了。

/**
 * @Auther: IT贱男
 * @Date: 2019/8/21 14:03
 * @Description:
 */
public class Test {

    public static void main(String[] args) {
        // 商家先做一个煎饼果子出来
        Apancake batterCake = new BatterCake();
        System.out.println(batterCake.getDesc() + " 价格:" + batterCake.cost());
        System.out.println("-------------------------");

        // 把做出来的煎饼果子加鸡蛋
        batterCake = new EggDecorate(batterCake);
        System.out.println(batterCake.getDesc() + " 价格:" + batterCake.cost());

        // 把已经加好鸡蛋的煎饼果子,再加一个火腿
        System.out.println("-------------------------");
        batterCake = new SausageDecorate(batterCake);
        System.out.println(batterCake.getDesc() + " 价格:" + batterCake.cost());

    }

}
煎饼果子 价格:5
-------------------------
煎饼果子加一个鸡蛋一元 价格:6
-------------------------
煎饼果子加一个鸡蛋一元加一个火腿肠加两元 价格:8

三、装饰者模式和桥接模式区别

桥接模式的定义是将抽象与实现分离(用组合聚合的方式,而不是使用继承),使得两者可以独立变化,可以减少创建新的类。这样看起来和装饰者模式差不多,但是两者还是有一些区别。

1、桥接模式中所指的分离,是将抽象和实现分离,而装饰者只是基于属性的行为进行封装成独立的类。

2、桥接模式中的行为之间是没有关联的,而装饰者模式中的行为具有可叠加性,其表现出来的结果是一个整体。

3、两者都可以减少子类过多的问题。


转载:https://blog.csdn.net/weixin_38111957/article/details/102060099
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场