巧妙的煎饼
问题提出:上班族大部分都吃过煎饼,煎饼一般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的书《设计模式就该这样学》, 这种处理方式叫 装饰器模式,之前学习设计模式总觉得很枯燥, 直到遇到这个例子才激发学习乐趣,这种接地气的代码印象深刻,写的巧妙值得反复思考