我有一个工厂返回IShape
类型。工厂建立如Circle
,Square
等具体类,如下所示。
public class ShapeFactory
{
public IShape GetShape(Shape shape, string name)
{
IShape s = null;
switch (shape)
{
case Shape.Square: s = new Square(name);
break;
case Shape.Triangle: s = new Triagle(name);
break;
case Shape.Circle: s = new Circle(name);
break;
}
return s;
}
}
用户可以编辑任何IShapes,但每个具体类都需要不同的对话框来编辑各种属性。检测形状类型的最佳方法是什么?
目前我有一个void Edit(IShape shape)
方法执行一系列if检查
public static void Edit(IShape shape)
{
if (shape == Square)
new EditSquare(shape as Square).ShowDialog();
else if (shape == Triangle)
new EditTriangle(shape as Triangle).ShowDialog();
}
这是一种合理的方法吗?什么是最好的方法。
编辑: 每个具体类派生自定义一些基本属性的抽象Shape类
public abstract class Shape
{
public string Name { get; set; }
public Rect Boundary { get; }
public double Area { get; protected set; }
}
IShape公开了一些用户想要执行的功能
public interface IShape
{
void Translate(Vector v);
void Calculate();
}
由于
答案 0 :(得分:4)
如果您需要根据对象的类型明确切换行为,那么它通常是设计错误的标志。每当您添加形状时,您都必须更新执行这些基于类型的开关的所有位置。
你的主要"武器"在这些情况下,polymorphism和virtual functions。
在最简单的方法中,您可以在IShape上创建一个自己创建编辑器的方法:
public interface IShape {
IShapeEditor CreateEditor();
}
public interface IShapeEditor {
void ShowDialog();
}
public class Square : IShape {
public IShapeEditor CreateEditor(){
return new SquareEditor(this);
}
}
public class Triangle: IShape {
public IShapeEditor CreateEditor(){
return new TriangleEditor(this);
}
}
public class Circle: IShape {
public IShapeEditor CreateEditor(){
return new CircleEditor(this);
}
}
在这种情况下,您的Edit方法可能如下所示:
public static void Edit(IShape shape)
{
shape.CreateEditor().ShowDialog();
}
这种方法的一个问题是你可能不想让形状知道编辑器。试图解决此问题的模式是visitor pattern。
使用访客模式可以是这样的:
public interface IShapeVisitor {
void VisitSquare(Square s);
void VisitTriangle(Triangle t);
void VisitCircle(Circle c);
}
public interface IShape {
void Accept(IShapeVisitor visitor);
}
public class Square : IShape {
public void Accept(IShapeVisitor visitor){
visitor.VisitSquare(this);
}
}
public class Triangle: IShape {
public void Accept(IShapeVisitor visitor){
visitor.VisitTriangle(this);
}
}
public class Circle: IShape {
public void Accept(IShapeVisitor visitor){
visitor.VisitCircle(this);
}
}
这是基本结构。对于编辑,您知道如下创建访问者:
public class EditorCreationVisitor : IShapeVisitor{
IShapeEditor editor;
public void VisitSquare(Square s ){
editor = new SquareEditor(s);
}
public void VisitTriangle(Triangle t ){
editor = new TriangleEditor(t);
}
public void VisitCircle(Circle c ){
editor = new CircleEditor(c);
}
public IShapeEditor Editor {get{return editor;}}
}
您的编辑方法将如下所示:
public static void Edit(IShape shape)
{
var visitor = new EditorCreationVisitor();
shape.Accept(visitor);
var editor = visitor.Editor;
editor.ShowDialog();
}
如果不同形状类型的数量相当恒定,则访问者模式效果最佳,但您会定期添加不同的行为。
答案 1 :(得分:0)
通常,您应该避免打开类型,因为在添加新形状类时这些将成为维护问题。而是在IShape界面中添加虚拟方法GetEditor()。然后你的代码变成:
public static void Edit(IShape shape)
{
shape.GetEditor().ShowDialog();
}
具体的形状类重写GetEditor()以返回特定于形状的编辑器子类。
答案 2 :(得分:0)
为什么不创建BaseShape抽象类并从BaseShape派生您的具体类? 在BaseShape中,您有抽象方法Edit(),因此派生类实现了相关行为。没有必要使用public static void Edit(IShape形状)。在你需要的地方调用你的shape.Edit()。