最近看了大話設計模式書中的裝飾者模式,然後用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#中這樣到底是怎麼執行的,有了解的請給我留言,萬分感謝