2013-05-06 94 views
1

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

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功能应接受一个枚举类型,然后返回单果重。我能够得到一个特定水果的物体,但是现在我从水果物体中得到了水果的重量。

此外,要添加到我的疑惑列表,我真的在此实现中遵循工厂模式?另外,互联网上的一些材料也使用抽象类?我应该遵循什么?接口实现还是应该使用抽象类并重写它?

在此先感谢您的帮助。

+0

我觉得'FruitsList'这个名字有点不对。你把它称为一个列表,但是当你把它传递给'GetFruitWeight'时,它就像一个标量(单个项目)一样使用它。它应该是一个'enum'吗? – 2013-05-06 08:34:44

+0

谢谢你指出马修。是的,它应该是一个枚举。 – 2013-05-06 09:03:10

回答

4

如果您不打算在返回对象时使用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(不要包装盒),并在fruit实例上调用ReturnFruitWeight的重量。

我真的遵循这个实现中的Factory模式吗?

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

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

这一切都取决于您的应用程序设计。举例来说,我个人只介绍一个抽象基类,如果:

  • 有共同的代码
  • 我需要确定的一些方法,我可以跨类共享某个特定类属于一个家庭的一个特定的类型,即Banana是一种Fruit

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

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 class VS interface,这两个选项都有效。如果您不想为您的方法提供默认实现,那么接口可能会更好,因为您可以实现多个接口,但不能从多个类继承。

+0

简单,我想要什么..谢谢Ken2k – 2013-05-06 09:06:09

0

我会做这样的事情:

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