C# 抽象工厂法;更改传递给对象的工厂

C# 抽象工厂法;更改传递给对象的工厂,c#,visual-studio-2010,design-patterns,C#,Visual Studio 2010,Design Patterns,在这个场景中,《星际迷航:TNG》的复制器出了问题,Guinan让我修复它。因为在有人告诉复制器之前,复制器不知道要做什么饮料,所以我们决定使用抽象工厂模式来创建饮料 public abstract class BoozeFactory { //create abstract methods public abstract Whiskey CreateWhiskey(); public abstract Rum CreateRum();

在这个场景中,《星际迷航:TNG》的复制器出了问题,Guinan让我修复它。因为在有人告诉复制器之前,复制器不知道要做什么饮料,所以我们决定使用抽象工厂模式来创建饮料

public abstract class BoozeFactory
    {
        //create abstract methods
        public abstract Whiskey CreateWhiskey();
        public abstract Rum CreateRum();

    }
    public class BlantonsFactory : BoozeFactory
    {
        public override Whiskey CreateWhiskey()
        {
            return new BlantonsWhiskey();
        }
        public override Rum CreateRum()
        {
            return new BlantonsRum();
        }
    }
    public class VobFactory : BoozeFactory
    {
        public override Whiskey CreateWhiskey()
        {
            return new VobWhiskey();
        }
        public override Rum CreateRum()
        {
            return new VobRum();
        }
    }
然后,我们深入研究了复制者可以吐出的品牌

 public abstract class Whiskey
    {
        public int Proof { get; set; }
        public abstract void DrinkingMethod();

    }
    public abstract class Rum
    {
        public int Proof { get; set; }
        public string Name { get; set; }
    }
    class BlantonsWhiskey : Whiskey
    {
        public override void DrinkingMethod()
        {
            Console.WriteLine("This is {0}, you should sip it",GetType().Name);
        }
    }
    class VobWhiskey : Whiskey
    {
        public override void DrinkingMethod()
        {
            Console.WriteLine("This is {0}, you should shoot it",GetType().Name);

        }
    }
    class BlantonsRum : Rum
    {
    }
    class VobRum : Rum
    {
    }
然后我们决定对数据进行重新编程,使其成为一个丰富的数据库

class Drinker
    {
        public BoozeFactory BoozeFactory { get; set; }
        public Whiskey Whiskey { get; set; }
        public Rum Rum { get; set; }

        public Drinker(BoozeFactory b)
        {
            //BoozeFactory is abstract and we will have to pass either a Blantons
            //or Vob factory to the constructor.  This way, the Whiskey and Rum
            //properties can depend on what is passed to the constructor at runtime
            BoozeFactory = b;
            Whiskey = BoozeFactory.CreateWhiskey();
            Rum = BoozeFactory.CreateRum();
        }
    }
这是我们测试的结果

Drinker data = new Drinker(new BlantonsFactory());
        data.Whiskey.DrinkingMethod();
        //woot, output is correct

        //the DrinkingMethod in the VobFactory class gives us different output
        data.BoozeFactory = new VobFactory(); //this is what's causing problems
        data.BoozeFactory.CreateWhiskey();
        data.Whiskey.DrinkingMethod();
        //even though the BoozeFactory property of data has been changed
        //the output hasn't changed

        BoozeFactory b = new VobFactory();
        data.Whiskey = b.CreateWhiskey();
        data.Whiskey.DrinkingMethod();
        //now the output is correct
为什么除非实例化BoozeFactory的新命名实例,否则对
data.wisky.DrinkingMethod()
的第二次调用将被忽略,但当我创建命名实例并对其进行测试时,它会起作用?

您的问题在于:

//the DrinkingMethod in the VobFactory class gives us different output
data.BoozeFactory = new VobFactory(); //this is what's causing problems
data.BoozeFactory.CreateWhiskey();
data.Whiskey.DrinkingMethod();
您从不将新威士忌分配给数据。威士忌属性,您创建它,然后立即丢弃它。你应该这样写你的第二行:

data.Whiskey = data.BoozeFactory.CreateWhiskey();

或者,更好的是,让饮酒者有一个方法来实现这一点。

测试结果的3行输出究竟是什么?对data.whisky.DrinkingMethod()的第一个调用是
Console.WriteLine(“这是{0},您应该sip它”,GetType().Name)Console.WriteLine(“这是{0},你应该拍摄它”,GetType().Name)
这是因为来自抽象类的重写DrinkingMethod
Whisky
我知道应该调用什么,如果我不理解继承和抽象,我不会尝试回答这个问题。我想问的是,控制台的输出是什么,一行接一行?i、 e.这是VobWhiskey,你应该啜一口(\n)这是VobWhiskey,你应该啜一口(\n)这是布兰顿威士忌,你应该开枪第一个电话是“这是布兰顿威士忌,你应该啜一口”,第二个电话是“这是VobWhiskey,你应该开枪”。