如何在 C# 中处理组合 类
How to handle composed classes in C#
我问的部分与设计模式有关。
假设我有一个 IDrawing 界面。
另外两个名为 TextDrawing 和 ShapeDrawing 的基本 classes 实现了这个,我有一个 View class 知道如何画这些!
但是我有更复杂的绘图 classes 也实现了 IDrawing 接口但是由几个 IDrawing class他们自己!
如何在我的 View class 中绘制这些?显然教 View class 绘制每个新的 IDrawing 不是一个好主意!但是我还有什么选择呢?也许设计不正确?我如何告诉 View 的 Draw 方法了解复杂 classes 的原始部分并绘制它们?
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() 方法的建议 classes。
View 中的 Draw 方法依赖外部库进行绘制(在我的例子中,它是 SkiaSharp 库)。如果我在这些 classes 中实现 Draw,它们将不再通用!例如,我将无法在其他项目中使用它们,在这些项目中我有不同的绘制策略。
您可以选择强制 classes 执行名为 Draw()
的方法。
public interface IDrawing
{
void Draw();
}
现在您可以简单地调用此方法并将内部实现的责任交给 classes 自己。
public void Draw(IDrawing drawing)
{
drawing.Draw();
例如TextDrawing
将被迫实施此方法
public class TextDrawing : IDrawing
{
public void Draw()
{
// draw Text-like
}
}
在您的 View
class 中,对 drawing.Draw();
的调用将导致正确的实现。
How can I tell the View's Draw method to know the primitive parts of the complex classes and draw them?
现在在复杂的 classes 中,您只需使用简单绘图中已经实现的方法 classes
public class SignDrawing : IDrawing
{
public TextDrawing Text { get; set; }
public ShapeDrawing Border { get; set; }
public void Draw()
{
Text.Draw();
Border.Draw();
Text.Draw();
}
}
我会向界面添加一个 Draw()
方法,并在您的每个 classes 中实现它。
这样做的好处是您的 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();
}
}
更新 - 抽象掉对 SkiaSharp
的依赖
您需要为 SkiaSharp
或实际执行绘图的任何外部依赖项创建一个包装器。这应该存在于与您的 IDrawing 接口相同的程序集中并派生 classes.
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);
}
也在更新您的 classes 以反映这一变化。您的 classes 将调用 IDrawingContext
实现上的方法来进行绘图。
在您的应用程序中创建依赖项特定实现并更新您的 View
class 以使用新的 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);
}
}
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.
我问的部分与设计模式有关。
假设我有一个 IDrawing 界面。 另外两个名为 TextDrawing 和 ShapeDrawing 的基本 classes 实现了这个,我有一个 View class 知道如何画这些!
但是我有更复杂的绘图 classes 也实现了 IDrawing 接口但是由几个 IDrawing class他们自己!
如何在我的 View class 中绘制这些?显然教 View class 绘制每个新的 IDrawing 不是一个好主意!但是我还有什么选择呢?也许设计不正确?我如何告诉 View 的 Draw 方法了解复杂 classes 的原始部分并绘制它们?
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() 方法的建议 classes。 View 中的 Draw 方法依赖外部库进行绘制(在我的例子中,它是 SkiaSharp 库)。如果我在这些 classes 中实现 Draw,它们将不再通用!例如,我将无法在其他项目中使用它们,在这些项目中我有不同的绘制策略。
您可以选择强制 classes 执行名为 Draw()
的方法。
public interface IDrawing
{
void Draw();
}
现在您可以简单地调用此方法并将内部实现的责任交给 classes 自己。
public void Draw(IDrawing drawing)
{
drawing.Draw();
例如TextDrawing
将被迫实施此方法
public class TextDrawing : IDrawing
{
public void Draw()
{
// draw Text-like
}
}
在您的 View
class 中,对 drawing.Draw();
的调用将导致正确的实现。
How can I tell the View's Draw method to know the primitive parts of the complex classes and draw them?
现在在复杂的 classes 中,您只需使用简单绘图中已经实现的方法 classes
public class SignDrawing : IDrawing
{
public TextDrawing Text { get; set; }
public ShapeDrawing Border { get; set; }
public void Draw()
{
Text.Draw();
Border.Draw();
Text.Draw();
}
}
我会向界面添加一个 Draw()
方法,并在您的每个 classes 中实现它。
这样做的好处是您的 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();
}
}
更新 - 抽象掉对 SkiaSharp
的依赖您需要为 SkiaSharp
或实际执行绘图的任何外部依赖项创建一个包装器。这应该存在于与您的 IDrawing 接口相同的程序集中并派生 classes.
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);
}
也在更新您的 classes 以反映这一变化。您的 classes 将调用 IDrawingContext
实现上的方法来进行绘图。
在您的应用程序中创建依赖项特定实现并更新您的 View
class 以使用新的 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);
}
}
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.