используя типы, созданные с помощью фабричного шаблона - PullRequest
4 голосов
/ 04 марта 2012

У меня есть фабричные типы возврата 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, но каждый конкретный класс требует отдельного диалога для редактирования различных свойств. Каков наилучший способ определения типа Shape? В настоящее время у меня есть метод 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(); 
}

Это разумный подход? Как лучше всего это сделать.

Edit: Каждый конкретный класс является производным от абстрактного класса 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 ]

4 голосов
/ 04 марта 2012

Обычно это признак плохого дизайна, если вам нужно явно переключать поведение в зависимости от типа объекта.Всякий раз, когда вы добавляете фигуру, вам придется обновлять все места, где вы используете эти переключатели на основе типов.

В этом случае вашими основными «оружием» являются полиморфизм и виртуальные функции.

В самом простом подходе у вас может быть метод на 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();
}

Проблема этого подхода заключается в том, что вы, возможно, не хотите, чтобы форма знала о редакторе.Шаблон, который пытается решить эту проблему - это шаблон посетителя .

Использование шаблона посетителя может выглядеть следующим образом:

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

Шаблон посетителей работает лучше всего, если число различныхтип фигуры довольно постоянен, но вы регулярно добавляете другое поведение.

0 голосов
/ 04 марта 2012

Почему бы вам не создать абстрактный класс BaseShape и не извлечь свой конкретный класс из BaseShape ?. В BaseShape у вас есть абстрактный метод Edit (), поэтому ваш производный класс реализует поведение corrent. Нет необходимости иметь открытый статический void Edit (форма IShape). Называйте свою форму. Редактируйте () везде, где это необходимо.

0 голосов
/ 04 марта 2012

Как правило, вам следует избегать включения типа, так как это станет проблемой обслуживания при добавлении новых классов фигур. Вместо этого добавьте виртуальный метод GetEditor () в ваш интерфейс IShape. Ваш код становится:

public static void Edit(IShape shape) 
{ 
  shape.GetEditor().ShowDialog(); 
} 

Конкретные классы фигур переопределяют GetEditor () для возврата подкласса редактора, специфичного для фигур.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...