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方法?
我在考虑一种工厂模式,但我真的不知道该怎么做.
我的水果类是否必须将抽屉作为财产?或者也许我可以调用抽屉工厂方法?
这是我在当前项目中发现很多的模式,我找不到满足我的解决方案.
一种方法是有一个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,Plotter并Printer让你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等等