如何重构方法调用哪个看起来一样?

Cyr*_*don 3 c# refactoring design-patterns

我有不同的水果类,都实现了相同的界面IFruit:

public interface IApple : IFruit{ }  
public interface IBanana : IFruit{ }  
public interface ICarrot: IFruit{ }  
Run Code Online (Sandbox Code Playgroud)

他们每个人都有自己的抽屉:

public class AppleDrawer
{
    public void Draw(IApple apple, Graphics graphics){}
}

public class BananaDrawer
{
    public void Draw(IBanana banana, Graphics graphics){}
}
Run Code Online (Sandbox Code Playgroud)

如果我想画一份水果清单,我会做以下事情

public void DrawFruits(List<IFruit> fruits, Graphics graphics)
{
    foreach(var fruit in fruits)
    {
        if(fruit is IBanana)
        {
            var banana = (IBanana)fruit;
            var drawer = new BananaDrawer();
            drawer.Draw(banana, graphics);
        }
        else if(fruit is IApple)
        {
            var apple = (IApple)fruit;
            var drawer = new AppleDrawer();
            drawer.Draw(banana, graphics);
        }
        etc...

}
Run Code Online (Sandbox Code Playgroud)

当我阅读我的代码时,我觉得非常脏.
我的问题是多个if..else语句,因为我有12个不同的水果,我必须在我当前的项目中做很多这样的陈述.

有没有办法重构我的DrawFruits方法?
我在考虑一种工厂模式,但我真的不知道该怎么做.
我的水果类是否必须将抽屉作为财产?或者也许我可以调用抽屉工厂方法?

这是我在当前项目中发现很多的模式,我找不到满足我的解决方案.

par*_*mar 5

一种方法是有一个GetDrawer对您的IFruit

public interface IFruit 
{
    BaseDrawer GetDrawer();
}
Run Code Online (Sandbox Code Playgroud)

和一个BaseDrawer界面

public interface BaseDrawer
{
    void Draw(IFruit fruit, Graphics graphics);
}.

public class AppleDrawer : BaseDrawer
{
    public void Draw(IFruit apple, Graphics graphics) { }
}

public class BananaDrawer : BaseDrawer
{
    public void Draw(IFruit banana, Graphics graphics) { }
}
Run Code Online (Sandbox Code Playgroud)

现在你的水果简单

   public void DrawFruits(List<IFruit> fruits, Graphics graphics)
    {
        foreach (var fruit in fruits)
        {
            var drawer = fruit.GetDrawer();
            drawer.Draw(fruit, graphics);
        }
    }
Run Code Online (Sandbox Code Playgroud)

有时你需要Drawer,PlotterPrinter让你IFruit可能会过于沉重像下面

public interface IFruit 
{
    BaseDrawer GetDrawer();
    BasePrinter GetPrinter();
    BasePlotter GetPlotter();
}
Run Code Online (Sandbox Code Playgroud)

访客模式是一个很好的解决方案.基本上你会有

 public interface iFruit
   {
      void Accept(FruitVisitor visitor);
   } 
Run Code Online (Sandbox Code Playgroud)

所有可能的绘图访问只有一个类

public class DrawVisitor : FruitVisitor 
   {
      public override void Visit(Apple apple)
      {
         //draw the apple
      }

      public override void Visit(Banana banana)
      { 
         // draw the banana
      }
   }
Run Code Online (Sandbox Code Playgroud)

在这里,你只需要一个DrawVisitor代替AppleDrawer,BananaDrawer等你的所有抽奖代码是整齐地在一个地方.你可能最终需要PlotterVisitor,PrinterVisiter等等