2012-03-04 42 views
4

我有一個工廠返回類型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; 
    } 
} 

用戶可以編輯任何I型,但每個具體類都需要不同的對話框來編輯各種屬性。檢測Shape的最佳方式是什麼? 目前,我有一個void Edit(IShape shape)方法,執行了一系列的檢查,如果

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

這是一個合理的方法呢?什麼是最好的方式去做這件事。

編輯: 每個具體類從抽象形狀類派生定義一些基本屬性

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

你能告訴我們IShape接口嗎?而你的具體類(Square,Circle等)則從基類(Shape)派生。 – Steve 2012-03-04 10:14:53

+0

你應該在代碼審查中發佈這個。 – Lloyd 2012-03-04 10:15:56

回答

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

在這種情況下,您的編輯方法可能看起來像:

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

Visitor模式效果最好,如果不同的形狀類型的數量是相當不變,但你會定期添加不同的行爲。

+0

謝謝你的安德烈。正如你所說,我想避免關於編輯器的對象「知道」,所以訪問者模式看起來就像是票。 – 2012-03-04 10:33:15

0

一般來說,你應該避免開啓類型,因爲當你添加新的形狀類時這些將成爲維護問題。相反,在IShape接口中添加虛擬方法GetEditor()。您的代碼將變爲:

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

具體形狀類重寫GetEditor()以返回形狀特定的編輯器子類。

0

爲什麼不創建BaseShape抽象類並從BaseShape派生具體類? 在BaseShape中,您有抽象方法Edit(),所以您的派生類實現了corrent行爲。沒有必要有一個公共靜態無效編輯(IShape形狀)。調用你的shape.Edit(),無論你需要它。

+0

我的形狀是在圖書館的dll,不能訪問UI對話框。我試圖保持形狀和UI分離,業務對象是否可以提供自己的UI組件。這當然使它更容易 – 2012-03-04 10:38:23