2

我有点能够理解工厂模式并想出了这个实现。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Enter the fruit name to get the Fruit!");
        string fruit = Console.ReadLine();

        FruitsList fruits;
        if (Enum.TryParse(fruit, true, out fruits))
        {
            var fruitWeight = GetFruitWeight(fruits);
            Console.ReadLine();
        }
        else
        {
            Console.WriteLine("Fruit Name is undefined!");
            Console.ReadLine();
        }
    }

    private static object GetFruitWeight(FruitsList fruitNumber)
    {
        switch (fruitNumber)
        {
            case FruitsList.Banana:
                return new Banana();
            case FruitsList.Apple:
                return new Apple();
        }

        return null;
    }
}

internal class Banana : IFruits
{
    public float ReturnFruitWeight()
    {
        return (float)10.00;
    }
}

public interface IFruits
{
    float ReturnFruitWeight();
}

public class Apple : IFruits
{
    public float ReturnFruitWeight()
    {
        return (float)30.00;
    }
}

public enum FruitsList
{
    Apple,
    Banana,
}

我的整个想法(从理论上的理解)是 GetFruitWeights 函数应该接受一个枚举类型,然后返回水果的重量。我能够获得特定水果的对象,但现在坚持如何从水果对象中获得水果的重量。

另外,为了增加我的疑虑,我真的在这个实现中遵循工厂模式吗?而且,互联网上的一些材料也使用抽象类?我应该遵循什么?接口实现还是我应该使用抽象类并覆盖它?

在此先感谢您的帮助。

4

4 回答 4

5

如果您在返回对象时无意使用该fruit对象,那么我将直接返回重量而不是水果对象。工厂方法名称实际上确实说它返回的是权重,而不是对象,所以理论上这是正确的方法,即

const float AppleWeight = 10;
const float BananaWeight = 10.4;
...
public static float GetFruitWeight(FruitList fruitType)
{
    switch (fruitType)
    {
        case FruitsList.Apple:
            return AppleWeight;
        case FruitsList.Banana:
            return BananaWeight;
        default:
            return 0;
    }
}

但是,如果您确实打算使用该fruit对象,那么我会将您的方法重命名为GetFruit,返回IFruits(不要装箱)并调用实例以获得权重ReturnFruitWeightfruit

我真的在这个实现中遵循工厂模式吗?

工厂模式的重点是允许您在不知道具体类型的情况下创建对象,所以是的,您在这里拥有的是工厂方法模式的一个相当基本的示例。

互联网上的一些材料也使用抽象类?我应该遵循什么?接口实现还是我应该使用抽象类并覆盖它?

这完全取决于您的应用程序设计。例如,我个人只会在以下情况下引入抽象基类:

  • 我可以在各个类之间共享通用代码
  • 我需要某种方法来确定特定类属于特定类型的家族,BananaFruit.

除此之外,我可能几乎总是会选择接口类型的方法。请记住,您可以同时拥有两者,没有理由不能拥有支持特定接口的抽象基类......

于 2013-05-06T08:26:44.097 回答
3

您可以遵循抽象类型或接口方法来实现工厂方法。例如,您的案例可以通过抽象来解决,因为您打算返回一个子类。

//Fruit base
    public abstract class Fruit
    {
        protected abstract string GetWeight();
    }
    public class Apple:Fruit
    {
        protected override string GetWeight()
        {
            return "I am from Apple";//replace with your implementation
        }
    }
    public class Banana : Fruit
    {
        protected override string GetWeight()
        {
            return "I am from Banana";//replace with your implementation
        }
    }



private static Fruit GetFruitWeight(string fruitNumber)
        {
            switch (fruitNumber)
            {
                case "Banana":
                    return new Banana();
                case "Apple":
                    return new Apple();
            }

            return null;
        }

现在我们应该在哪里使用接口方法?

就个人而言,我在希望返回服务的工厂方法中遵循接口方法。例如。假设一个工厂方法返回一个电子邮件发件人服务,我可以在其中为 Outlook 或其他一些电子邮件服务实现服务。

public class Outlook:ISender
    {

        public void SendEmail()
        {
            //Write implementation on how OL send email.
        }
    }
    public class OtherEmail : ISender
    {

        public void SendEmail()
        {
            //Write implementation on how other email send email.
        }
    }
    public interface ISender
    {
        void SendEmail();
    }
    public class EmailFactory
    {

        public static ISender GetEmailProvider(string type)
        {
            if (type == "outlook")
                return new Outlook();
            return new OtherEmail();
        }
    }
于 2013-05-06T08:52:29.873 回答
1

我会做这样的事情:

public interface IFruit
{
    string Name { get; set; }
    decimal GetWeight();
}

public class Fruit : IFruit
{
    protected decimal Weight;

    public string Name { get; set; }

    public decimal GetWeight()
    {
        return Weight;
    }
}

public class Apple : Fruit
{
    public Apple()
    {
        Name = "Granny Smith";
        Weight = (decimal) 2.1;
    }
}

public class Banana : Fruit
{
    public Banana()
    {
        Name = "Cavendish";
        Weight = (decimal) 1.5;
    }
}

public enum FruitType
{
    Apple,
    Banana        
}

public static class FruitFactory
{
    public static IFruit CreateFruit(FruitType f)
    {
        switch(f)
        {
            case FruitType.Banana: return new Banana();
            case FruitType.Apple: return new Apple();
            default: return null;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var apple = FruitFactory.CreateFruit(FruitType.Apple);
        var banana = FruitFactory.CreateFruit(FruitType.Banana);

        Console.WriteLine(apple.Name + " " + apple.GetWeight());
        Console.WriteLine(banana.Name + " " + banana.GetWeight());
    }
}
于 2013-05-06T08:49:34.033 回答
1

不要返回一个object,而是一个IFruits。此外,重命名您的静态方法,因为它返回水果,而不是它们的重量:

private static IFruits GetFruit(FruitsList fruitNumber)
{
    switch (fruitNumber)
    {
        case FruitsList.Banana:
            return new Banana();
        case FruitsList.Apple:
            return new Apple();
    }

    return null;  // Maybe you can throw a ArgumentException here
}
...
var theFruit = GetFruit(fruits);
var weight = theFruit.ReturnFruitWeight();

对于abstract classvs interface,这两个选项都有效。如果您不想为方法提供默认实现,那么接口可能会更好,因为您可以实现多个接口但不能从多个类继承。

于 2013-05-06T08:31:04.900 回答