Прежде всего, нам нужно улучшить ваш дизайн.
Фабричный шаблон имеет смысл, только если вы кодируете абстракцию, а это значит, что фабрика должна создать конкретный тип, но вы не должны знать конкретный тип, а только абстрактный тип. Это не так в вашем дизайне. Вы говорите, что используете абстрактный шаблон фабрики, но приводите созданный объект к Circle, который является «кодированием для реализации».
Компилятор как компилирует строки в Shapes, так и выполняет их. Компилятор должен только преобразовывать текст (код) в исполняемый объект и не должен их выполнять. К сожалению, с вашим текущим дизайном невозможно передать созданные формы в выходную форму и нарисовать их.
Вам нужно передать все скомпилированные формы в выходную форму, и должен рисовать в переопределении OnPaint, когда среда выполнения перерисовывает поверхность элемента управления (форма)
Абстракция (форма):
public abstract class Shape
{
public abstract void Draw(Graphics surface);
}
И конкретные типы:
public class Circle : Shape
{
public float Radius { get; set; }
public override void Draw(System.Drawing.Graphics surface)
{
surface.DrawEllipse(Pens.Black, 0, 0, Radius, Radius);
}
}
public class Rectangle : Shape
{
public float Width { get; set; }
public float Height { get; set; }
public override void Draw(System.Drawing.Graphics surface)
{
surface.DrawRectangle(Pens.Black, 0, 0, Width, Height);
}
}
Вот ShapeFactory в моей реализации
public class ShapeFactory
{
public static Shape CreateShape(string shapeName, params string[] parameters)
{
switch (shapeName)
{
case "circle":
return new Circle() { Radius = Convert.ToSingle(parameters[0]) };
case "rectangle":
return new Rectangle { Width = Convert.ToSingle(parameters[0]), Height = Convert.ToSingle(parameters[1]) };
default:
throw new NotSupportedException("shapeName");
}
}
}
Компилятор:
public Shape Compile(string line)
{
string[] code = line.Split(new char[] { ',', '(', ')' }, StringSplitOptions.RemoveEmptyEntries);
if (IsSyntax(code[0]))
{
try
{
return ShapeFactory.CreateShape(code[0], code.Skip(1).ToArray());
}
catch (Exception shapeCreationException)
{
// Exception handling here.
// . . .
}
}
else
{
// Syntax Error handling here
// . . .
}
return null;
}
И, наконец, форма вывода:
public partial class Output : Form
{
public List<Shape> Shapes { get; set; }
public Output()
{
Shapes = new List<Shape>();
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
foreach (Shape shapeToDraw in Shapes)
{
shapeToDraw.Draw(e.Graphics);
}
}
}
и метод execute ():
private void execute()
{
Output outputWindow = new Output();
Compiler compiler = new Compiler();
string[] lines = { "circle(24)", "rectangle(80,56)" };
foreach (var line in lines)
{
try
{
Shape compiledShape = compiler.Compile(line);
outputWindow.Shapes.Add(compiledShape);
}
catch
{
// Exception handling here
// . . .
}
}
outputWindow.Show();
outputWindow.Invalidate();
}
Это проверено и работает.
Пожалуйста, прокомментируйте, если вы чего-то не понимаете или не можете получить это работать, но, к сожалению, ваш случай не так просто исправить из-за его конструкции fl aws.