如何避免子类的工厂方法中的 switch-case

发布于 2024-11-04 20:36:13 字数 801 浏览 0 评论 0原文

假设我们有一个类系列(卡,为了它),我们需要根据一些标识符实例化它们。 工厂方法看起来像这样:

public Card GetCard(int cardNumber) 
{
   switch(cardNumber) 
   {
     case 13: return new King();
     case 12: return new Queen();
     case 11: return new Jack();          
   }

   //...
}

我想要的是避免这个switch。为什么?也许我想在功能中重复使用这个比较。

我想出的是这样的:

private Dictionary<int, Type> cardTypes = 
 { 
   {13, typeof(King)},
   {12, typeof(Queen)},
   {11, typeof(Jack)}
 };

 public Card GetCard(int cardNumber) 
 {        
    var cardType = cardTypes[cardNumber];
    var instance = Activator.CreateInstance(cardType);
    return (Card)instance;
 }

然而,这个解决方案使用反射,这是昂贵的,并且当你有多个“标识符”时也会出现问题(例如 1 和 14 都给出 Ace -我应该向字典添加 2 个键吗?)。

这种情况下的最佳实践是什么?

Lets say we have a family of classes (cards, for the sake of it), and we need to instantiate them based on some identifier.
A factory method would look like this:

public Card GetCard(int cardNumber) 
{
   switch(cardNumber) 
   {
     case 13: return new King();
     case 12: return new Queen();
     case 11: return new Jack();          
   }

   //...
}

What I want is to avoid this switch. Why? Maybe I want to reuse this comparison in the feature.

What I came up with is something like this:

private Dictionary<int, Type> cardTypes = 
 { 
   {13, typeof(King)},
   {12, typeof(Queen)},
   {11, typeof(Jack)}
 };

 public Card GetCard(int cardNumber) 
 {        
    var cardType = cardTypes[cardNumber];
    var instance = Activator.CreateInstance(cardType);
    return (Card)instance;
 }

However, this solution uses reflection which is expensive, and is also problematic when you have more than one "identifier" (for example 1 and 14 both give Ace - should I add 2 keys to the dictionary?).

What's the best practice in this scenario?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

悟红尘 2024-11-11 20:36:13

您可以存储一个 Func,而不是将 type 存储在字典中:

private Dictionary<int, Func<Card>> cardFactories = 
{
    { 13, () => new King() },
    // etc
}

public Card GetCard(int cardNumber) 
{        
    var factory = cardFactories[cardNumber];
    return factory();
}

对于卡片,我可能会让它们一开始就不可变,只是用卡片本身填充字典,但这是另一回事:)

Instead of storing the type in the dictionary, you could store a Func<Card>:

private Dictionary<int, Func<Card>> cardFactories = 
{
    { 13, () => new King() },
    // etc
}

public Card GetCard(int cardNumber) 
{        
    var factory = cardFactories[cardNumber];
    return factory();
}

In the case of cards, I'd probably make them immutable to start with and just populate the dictionary with the cards themselves, but that's a different matter :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文