我所问的部分与设计模式有关。
假设我有一个 IDrawing 界面。 另外两个名为 TextDrawing 和 ShapeDrawing 的基本类实现了这个,我有一个知道如何绘制这些类的View类!
但我有更复杂的绘图类,它们也实现了 IDrawing 界面,但它们本身由几个 IDrawing 类组成!
如何在 查看 类中绘制这些内容?显然,教授 View 类来绘制每个新的 IDrawing 并不是一个好主意!但我还有其他选择吗?也许设计不正确?如何告诉View的Draw方法知道复杂类的原始部分并绘制它们?
public interface IDrawing
{
}
public class TextDrawing : IDrawing
{
}
public class ShapeDrawing : IDrawing
{
}
public class SignDrawing : IDrawing
{
public TextDrawing Text { get; set; }
public ShapeDrawing Border { get; set; }
}
public class MoreComplexDrawing : IDrawing
{
public TextDrawing Text { get; set; }
public ShapeDrawing Border1 { get; set; }
public ShapeDrawing Border2 { get; set; }
}
public class View
{
public void Draw(IDrawing drawing)
{
// The View only knows how to draw TextDrawing and ShapeDrawing.
// These as the primitive building blocks of all drawings.
// How can it draw the more complex ones!
if (drawing is TextDrawing)
{
// draw it
}
else if (drawing is ShapeDrawing)
{
// draw it
}
else
{
// extract the drawings primitive parts (TextDrawing and ShapeDrawing) and draw them!
}
}
}
更新
我收到了在绘图类中实现Draw()方法的建议。 View中的Draw方法依赖于要绘制的外部库(在我的例子中,它是SkiaSharp库)。如果我在这些类中实现Draw,它们将不再是通用的!例如,我将无法在其他项目中使用它们,因为我有不同的策略来绘制东西。
答案 0 :(得分:5)
我会在接口中添加Draw()
方法,并在每个类中实现它。
这样做的好处是,View
并不关心实际类型。
public interface IDrawing
{
void Draw();
}
public class TextDrawing : IDrawing
{
public void Draw()
{
// Draw a TextDrawing
}
}
public class ShapeDrawing : IDrawing
{
public void Draw()
{
// Draw a ShapeDrawing
}
}
public class SignDrawing : IDrawing
{
public TextDrawing Text { get; set; }
public ShapeDrawing Border { get; set; }
public void Draw()
{
// Draw a SignDrawing
}
}
public class MoreComplexDrawing : IDrawing
{
public TextDrawing Text { get; set; }
public ShapeDrawing Border1 { get; set; }
public ShapeDrawing Border2 { get; set; }
public void Draw()
{
// Draw a MoreComplexDrawing
}
}
public class View
{
public void Draw(IDrawing drawing)
{
//Draw the drawing
drawing.Draw();
}
}
UPDATE - 摘要对SkiaSharp的依赖
您需要为SkiaSharp
或任何实际执行绘图的外部依赖项创建包装器。这应该与IDrawing接口和派生类存在于同一个程序集中。
public interface IDrawingContext
{
// Lots of drawing methods that will facilitate the drawing of your `IDrawing`s
void DrawText(...);
void DrawShape(...);
void DrawBorder(...);
}
以及SkiaSharp
具体实施
public class SkiaSharpDrawingContext IDrawingContext
{
// Lots of drawing methods that will facilitate the drawing of your IDrawings
public void DrawText(...) { /* Drawing code here */ }
public void DrawShape(...) { /* Drawing code here */ }
public void DrawBorder(...) { /* Drawing code here */ }
}
将IDrawing
界面更新为
public interface IDrawing
{
void Draw(IDrawingContext drawingContext);
}
更新您的课程以反映此更改。您的类将调用IDrawingContext
实现上的方法来进行绘制。
在您的应用程序中创建特定于依赖项的实现,并更新您的View
类以使用新的SkiaSharpDrawingContext
public class View
{
public void Draw(IDrawing drawing)
{
// This should ideally be injected using an IOC framework
var drawingContext = new SkiaSharpDrawingContext(...);
//Draw the drawing
drawing.Draw(drawingContext);
}
}
答案 1 :(得分:4)
您可以选择强制类实现名为Draw()
的方法。
public interface IDrawing
{
void Draw();
}
现在你可以简单地调用这个方法,并将内部实现的责任交给自己。
public void Draw(IDrawing drawing)
{
drawing.Draw();
例如,TextDrawing
将被迫实施此方法
public class TextDrawing : IDrawing
{
public void Draw()
{
// draw Text-like
}
}
在View
课程中,对drawing.Draw();
的调用将导致正确的实施。
如何告诉View的Draw方法知道复杂类的原始部分并绘制它们?
现在在复杂的类中,您只需使用已经在简单绘图类中实现的方法
public class SignDrawing : IDrawing
{
public TextDrawing Text { get; set; }
public ShapeDrawing Border { get; set; }
public void Draw()
{
Text.Draw();
Border.Draw();
Text.Draw();
}
}
答案 2 :(得分:2)
you can polymorphically draw without checking the type.
public class View
{
public void Draw(IDrawing drawing)
{
drawing.Draw();
}
}
Encapsulate each drawing strategy (Strategy Pattern) in different class and you could inject each strategy via DI.