Using types created using the factory pattern

I have factory returned IShape types. factory builds specific classes such as Circle , Square , etc., as shown below.

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

The user can edit any of the IShapes, but each particular class requires a different dialog box for editing various properties. What is the best way to determine the type of form? I currently have a void Edit(IShape shape) method that performs a series of checks

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

Is this a smart approach? What is the best way to do this.

Edit: Each particular class derives from an abstract Shape class that defines some basic properties.

 public abstract class Shape { public string Name { get; set; } public Rect Boundary { get; } public double Area { get; protected set; } } 

IShape provides some of the features that a user would like to perform.

 public interface IShape { void Translate(Vector v); void Calculate(); } 

thanks

+4
source share
3 answers

This is usually a sign of poor design if you need to explicitly switch behavior based on the type of object. Whenever you add a shape, you will have to update all the places where you use these type-based switches.

Your main "weapon" in such cases is polymorphism and virtual functions .

In the easiest approach, you can have an IShape method that the editor creates on its own:

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

In this case, your editing method might look like this:

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

The problem with this approach is that you may not want the form to know about the editor. The pattern that is trying to solve this problem is the pattern.

Using a visitor template might look like this:

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

This is the basic structure. For the editor you know, create such a visitor:

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

Your editing method will now look like this:

 public static void Edit(IShape shape) { var visitor = new EditorCreationVisitor(); shape.Accept(visitor); var editor = visitor.Editor; editor.ShowDialog(); } 

The visitor pattern works best if the number of different types of shapes is fairly constant, but you regularly add different behavior.

+4
source

In general, you should avoid including a type, as this will become a maintenance problem when adding new form classes. Instead, add the virtual GetEditor () method to your IShape interface. Then your code will look like this:

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

Specific form classes override GetEditor () to return a subclass of the specific format editor.

0
source

Why don't you create an abstract BaseShape class and get your specific class from BaseShape ?. In BaseShape, you have an abstract Edit () method, so your derived class implements corrent behavior. There is no need to have a public static void Edit (IShape form). Call the .Edit () form where you need it.

0
source

Source: https://habr.com/ru/post/1399625/


All Articles