使用使用工厂模式创建的类型

时间:2012-03-04 10:07:13

标签: c# design-patterns

我有一个工厂返回IShape类型。工厂建立如CircleSquare等具体类,如下所示。

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();
}

由于

3 个答案:

答案 0 :(得分:4)

如果您需要根据对象的类型明确切换行为,那么它通常是设计错误的标志。每当您添加形状时,您都必须更新执行这些基于类型的开关的所有位置。

你的主要"武器"在这些情况下,polymorphismvirtual 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()。