C# C语言中的工厂模式#

C# C语言中的工厂模式#,c#,.net,design-patterns,.net-4.5,C#,.net,Design Patterns,.net 4.5,我有点能够理解工厂模式,并提出了这个实现 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

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

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函数应接受枚举类型,然后返回水果权重。我能得到一个特定水果的物体,但现在我想知道如何从水果物体中得到水果的重量

另外,在我的疑问列表中,我在这个实现中是否真的遵循了工厂模式?而且,互联网上的一些材料也使用了抽象类?我应该遵循什么?接口实现,还是应该使用抽象类并重写它


提前感谢您的帮助。

如果您不打算在返回水果时使用
水果
对象,那么我将直接返回重量,而不是水果对象。factory方法名称实际上表示它返回的是权重,而不是对象,因此理论上它是正确的方法,即

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
(不要框),并在
fruit
实例上调用
ReturnFruitWeight
以获取权重

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

factory模式的要点是允许您在不知道具体类型的情况下创建对象,因此,这里是factory方法模式的一个相当基本的示例

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

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

  • 我可以在各个类之间共享一些通用代码
  • 我需要某种方法来确定某个特定的类属于某个特定类型的族,即
    香蕉
    水果
    的一种类型

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

如果在返回时不打算使用
fruit
对象,那么我将直接返回权重而不是fruit对象。factory方法名称实际上表示它返回的是权重,而不是对象,因此理论上它是正确的方法,即

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
(不要框),并在
fruit
实例上调用
ReturnFruitWeight
以获取权重

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

factory模式的要点是允许您在不知道具体类型的情况下创建对象,因此,这里是factory方法模式的一个相当基本的示例

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

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

  • 我可以在各个类之间共享一些通用代码
  • 我需要某种方法来确定某个特定的类属于某个特定类型的族,即
    香蕉
    水果
    的一种类型

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

不要返回
对象,而是返回
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();

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

不要返回
对象,而是返回
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();

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

我会这样做:

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());
    }
}

我会这样做:

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());
    }
}

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

//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();
        }
    }

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

//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();
        }
    }

我觉得水果列表的名字有点不对。您将其称为列表,但在将其传递给
GetFruitWeight
时,将其用作标量(单个项目)。是晚餐吗