抽象工厂方法;更改工厂传递给对象

时间:2013-07-09 19:59:26

标签: c# visual-studio-2010 design-patterns

在这种情况下,“星际迷航:TNG”的复制者一直在使用fritz而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.Whiskey.DrinkingMethod()的第二次调用,但是当我创建命名实例并对其进行测试时,它是否有效?

1 个答案:

答案 0 :(得分:1)

你的问题在这里:

//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.Whiskey = data.BoozeFactory.CreateWhiskey();

或者,更好的是,让饮酒者有一种方法可以做到这一点。