巧妙的煎饼

问题提出:上班族大部分都吃过煎饼,煎饼一般5块钱,可以额外加码比如鸡蛋+1元,香肠+2元。 编写一个程序 可以 快速计算出 煎饼 多少钱。
大部分人写的代码:
首先建个煎饼类,最基础的类:

public class Battercake {
    protected String getMsg(){
        return "煎饼";
    }
    public int getPrice(){
        return 5;
    }
}

再建个鸡蛋煎饼类,继承煎饼类然后修改价格

public class BattercakeWithEgg extends Battercake{
    protected String getMsg(){
        return super.getMsg() + "+1个鸡蛋";
    }
    public int getPrice(){
        return super.getPrice() + 1;
    }
}

再在鸡蛋煎饼的基础上加个香肠

public class BattercakeWithEggAndSauage extends BattercakeWithEgg{、
    protected String getMsg(){
        return super.getMsg() + "+1根香肠";
    }
    public int getPrice(){
        return super.getPrice() + 2;
    }
}

测试一下:

public static void main(String[] args) {
        Battercake battercake = new Battercake();
        System.out.println(battercake.getMsg() + ",总价:" + battercake.getPrice());

        BattercakeWithEgg battercakeWithEgg = new BattercakeWithEgg();
        System.out.println(battercakeWithEgg.getMsg() + ",总价:" + battercakeWithEgg.getPrice());

        BattercakeWithEggAndSauage battercakeWithEggAndSauage = new BattercakeWithEggAndSauage();
        System.out.println(battercakeWithEggAndSauage.getMsg() + ",总价:" + battercakeWithEggAndSauage.getPrice());
    }

运行结果:

"D:\Program Files\Java\jdk1.8.0_181\bin\java.exe" 
煎饼,总价:5
煎饼+1个鸡蛋,总价:6
煎饼+1个鸡蛋+1根香肠,总价:8

代码写到这儿,感觉很easy,没毛病。但是如果 我想加两个鸡蛋 怎么办呢,难道再写一个类?我不想加蛋,只要个香肠又怎么办呢。这个需求完全没问题,代码如何灵活变化呢。
我们来看一位老师给出的代码:
首先创建一个抽象类:

public abstract class Battercake {
    protected abstract String getMsg();
    protected abstract int getPrice();
}

再创建一个煎饼类:

public class BaseBattercake extends Battercake {
    protected String getMsg() {
        return "煎饼";
    }
    protected int getPrice() {
        return 5;
    }
 }

重点来了,创建一个抽象扩展类,仔细看下面的代码

public abstract class BattercakeDecorator extends Battercake {

    //用了抽象类当一个属性
    private Battercake battercake;

    public BattercakeDecorator(Battercake battercake) {
        this.battercake = battercake;
    }

    public abstract void doSomething();

    protected String getMsg() {
        return this.battercake.getMsg();
    }

    protected int getPrice() {
        return this.battercake.getPrice();
    }
}

最后创建鸡蛋类的扩展:

public class EggDecorator extends BattercakeDecorator {
    public EggDecorator(Battercake battercake) {
        super(battercake);
    }

    public void doSomething() {

    }

    @Override
    protected String getMsg() {
        return super.getMsg() + "1个鸡蛋";
    }

    @Override
    protected int getPrice() {
        return super.getPrice() + 1;
    }
}

香肠类的扩展:

public class SausageDecorator extends BattercakeDecorator {
    public SausageDecorator(Battercake battercake) {
        super(battercake);
    }

    public void doSomething() {

    }

    @Override
    protected String getMsg() {
        return super.getMsg() + "1根香肠";
    }

    @Override
    protected int getPrice() {
        return super.getPrice() + 2;
    }
}


测下代码:

public static void main(String[] args) {

        Battercake battercake;

        battercake = new BaseBattercake();

        //加个蛋
        battercake = new EggDecorator(battercake);

		//加个蛋
        battercake = new EggDecorator(battercake);

 		//加个肠
        battercake = new SausageDecorator(battercake);

        System.out.println(battercake.getMsg() + ",总价:" + battercake.getPrice());
"D:\Program Files\Java\jdk1.8.0_181\bin\java.exe"
煎饼1个鸡蛋1个鸡蛋1根香肠,总价:9

有没有觉得的很神奇,通过抽象类,继承,构造函数里传入接口对象,完成了自由扩展特性。想加几个蛋就加几个,不必再去修改计算逻辑。

这部分代码实际来自 Tom的书《设计模式就该这样学》, 这种处理方式叫 装饰器模式,之前学习设计模式总觉得很枯燥, 直到遇到这个例子才激发学习乐趣,这种接地气的代码印象深刻,写的巧妙值得反复思考

posted @ 2024-08-16 18:42  changlong2022  阅读(27)  评论(0编辑  收藏  举报