我有点能理解Factory Pattern并想出了这个实现。
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模式?而且,互联网上的一些材料也使用抽象类?我该怎么办?接口实现还是应该使用抽象类并覆盖它?
提前感谢您的帮助。
答案 0 :(得分: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
(不要选中)并致电ReturnFruitWeight
在fruit
重量实例上。
我是否真的在这个实现中遵循工厂模式?
工厂模式的要点是允许你在不知道具体类型的情况下创建对象,所以你在这里拥有的是工厂方法模式的一个相当基本的例子。
互联网上的一些材料也使用抽象类?我该怎么办?接口实现还是应该使用抽象类并覆盖它?
这完全取决于您的应用程序设计。例如,我个人只会在以下情况下引入抽象基类:
Banana
是Fruit
的类型。除此之外,我可能几乎总是采用接口类型的方法。请记住,你可以同时拥有这两者,没有理由不能拥有支持特定接口的抽象基类......
答案 1 :(得分: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();
}
}
答案 2 :(得分: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
,这两个选项都有效。如果您不想为方法提供默认实现,那么接口可能会更好,因为您可以实现多个接口但不能从多个类继承。
答案 3 :(得分: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());
}
}