大話設計模式-裝飾者模式C#與Java對比存在的問題

最近看了大話設計模式書中的裝飾者模式,然後用C#照着寫了一遍,發現運行出來的結果和書上不一樣,然後又用Java寫了一遍 和書上一樣,同樣的代碼,不同的編譯器與運行環境,Java和.NET 下面貼上代碼
首先是Java實現
Beverage(飲料抽象類)
CondimentDecorator(調料抽象類,繼承Beverage)
Latte(拿鐵飲料,繼承Beverage)
Mocha(摩卡調料,繼承CondimentDecorator)

public abstract class Beverage {
    public String description = "Unkonw";
    public String getDescription(){
        return description; 
    }
    public abstract double cost();
}
public abstract class CondimentDecorator extends Beverage {
    public abstract String getDescription();
}
public class Latte extends Beverage {
    public Latte(){
        description = "Latte Coffee";
    }
    @Override
    public double cost() {
        // TODO Auto-generated method stub
        return 21.05;
    }
}
public class Mocha extends CondimentDecorator {

    Beverage beverage;
    public Mocha(Beverage beverage){
        this.beverage = beverage;
    }
    @Override
    public String getDescription() {
        // TODO Auto-generated method stub
        return beverage.getDescription() + ", Mocha Condiment";
    }
    @Override
    public double cost() {
        // TODO Auto-generated method stub
        return .99 + beverage.cost();
    }

}
public static void main(String[] args) {
        // TODO Auto-generated method stub

        Beverage beverage1 = new Latte();
        beverage1 = new Mocha(beverage1);
        System.out.println("小明點了:"+beverage1.getDescription()+"咖啡,花了:"+beverage1.cost()+" RMB");
    }

運行結果
這裏寫圖片描述

下面看下C#中的實現

Beverage(飲料抽象類)
CondimentDecorator(調料抽象類,繼承Beverage)
Espresso(濃咖啡,繼承Beverage)
SoyMilk(豆奶調料,繼承CondimentDecorator)

public abstract class Beverage
    {
        public string description = "Unknow"; 
        public string getDescription() 
        {
            return description;
        }

        public abstract double cost();

    }
public abstract class CondimentDecorator:Beverage
    { 
        public abstract string getDescription();
    }
public class Espresso :Beverage
    {
        public Espresso() 
        {
            description = "Espresso Coffee(濃咖啡)";
        }

        public override double cost()
        {
            return 19.00;
        }
    }
public class SoyMilk:CondimentDecorator
    {
        private Beverage beverage;
        public SoyMilk(Beverage bev) 
        {
            this.beverage = bev;
        }

        public override string getDescription()
        {
            return beverage.getDescription() + "SoyMilk(豆奶調料)";
        }

        public override double cost()
        {
            return 1.25 + beverage.cost();
        }
    }
public static void Main(string[] args)
        { 
            Beverage espresso = new Espresso(); 
            espresso = new SoyMilk(espresso);
            Console.WriteLine("小張點了一杯:" + espresso.getDescription() + " 咖啡, 價格是:" + espresso.cost() + " RMB");

            Console.ReadLine();
        }

可以看出,除了飲料名稱之外,代碼都是一樣的,下面是運行結果
這裏寫圖片描述

和上面Java的結果對比確實不一樣,下面把C#中的Beverage和CondimentDecorator改一下
把Beverage的getDescription方法寫成虛方法

public virtual string getDescription() 
        {
            return description;
        }

然後把CondimentDecorator的加上override

public abstract override string getDescription();

下面是運行結果
這裏寫圖片描述

這樣就正常了,是不是很神奇

來分析一下Java中執行步驟

Beverage beverage1 = new Latte(); //父類實例化Latte
        beverage1 = new Mocha(beverage1); //Latte作爲參數實例化Mocha
        //beverage1getDescription首先調用Mocha中的getDescription方法,然後再調用Latte裏面的getDescription方法(隱式繼承了父類)
beverage1.getDescription();

一直搞不懂C#中這樣到底是怎麼執行的,有了解的請給我留言,萬分感謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章