I had an exercise as below for an interview. I've added my implementation at the end. How could I improve it?
Exercise description:
Develop a simple vector based drawing package.
Your application should support the following 5 drawing primitives (we will call them widget)
1) rectangle 2) square 3) ellipse 4) circle 5) textbox
The application should allow a user to add a new widget to the drawing, stating the location and size / shape of the widget. The location can be a standard x/y coordinate on an imaginary page. The size/shape depends on the widget, as follows:
- rectangle - width and height
- square - width
- ellipse - horizontal and vertical diameter
- circle - diameter
- textbox - bounding rectangle (i.e, the rectangle which surronds the textbox; the text will be centred within this rectangle)
Notes:
- you don't need to actually render the widgets in any manner - we're just simulating a drawing package at this stage
- your application can add a hard coded set of widgets to the drawing at the bootstrap, no real user input. Please add one of each widget to the drawing.
My implementation:
bootstrap.php
/*
* rectangle x=10, y=10, width=30, height=40
*/
$renderEngine = new CliRenderer();
$renderEngine->render("
-------------------------------\n
Current drawing\n
------------------------------\n
");
$rectangle = new WidgetFactory(new Widget(10,10), new Rectangle(30, 40), $renderEngine);
$rectangle->draw();
/*
* square x=15, y=30, size=35
*/
$square = new WidgetFactory(new Widget(15, 30), new Square(35), $renderEngine);
$square->draw();
/*
* ellipse x=100, y=150, horizontal diameter=300, vertical diameter=200
*/
$ellipse = new WidgetFactory(new Widget(100, 150), new Elipse(300, 200), $renderEngine);
$ellipse->draw();
/**
* circle x=1, y=1, size=300
*/
$circle = new WidgetFactory(new Widget(1,1), new Square(300), $renderEngine);
$circle->draw();
/*
* textbox x=5, y=5, width=200, height=100, text="sample text"
*/
$textBox = new WidgetFactory(new Widget(5,5), new TextBox(200, 100, "sample text"), $renderEngine);
$textBox->draw();
$renderEngine->render("------------------------------");
RenderEngineInterface.php
<?php
interface RenderEngineInterface
{
public function render($str);
}
CliRenderer.php
<?php
class CliRenderer implements RenderEngineInterface
{
public function render($str)
{
echo $str."\n";
}
}
WidgetFactory.php
<?php
class WidgetFactory
{
private $widget;
private $shape;
private $renderEngine;
function __construct(WidgetInterface $widget,ShapeInterface $shape,RenderEngineInterface $renderEngine)
{
$this->widget = $widget;
$this->shape = $shape;
$this->renderEngine = $renderEngine;
}
public function draw()
{
return $this->renderEngine->render($this->shape->output($this->widget));
}
}
WidgetInterface.php
<?php
interface WidgetInterface
{
public function getX();
public function getY();
}
Widget.php
class Widget implements WidgetInterface
{
private $x;
private $y;
function __construct($x, $y)
{
$this->x = $x;
$this->y = $y;
}
/**
* @return mixed
*/
public function getX()
{
return $this->x;
}
/**
* @param mixed $x
*/
public function setX($x)
{
$this->x = $x;
}
/**
* @return mixed
*/
public function getY()
{
return $this->y;
}
/**
* @param mixed $y
*/
public function setY($y)
{
$this->y = $y;
}
}
ShapeInterface.php
<?php
interface ShapeInterface
{
public function output(WidgetInterface $widget);
}
Circle.php
<?php
class Circle implements ShapeInterface
{
private $size;
function __construct($size)
{
$this->size = $size;
}
/**
* @return mixed
*/
public function getSize()
{
return $this->size;
}
/**
* @param mixed $size
*/
public function setSize($size)
{
$this->size = $size;
}
public function output(WidgetInterface $widget)
{
return "circle (".$widget->getX().",".$widget->getY().") size=".$this->size;
}
}
Elipse.php
<?php
class Elipse implements ShapeInterface
{
private $diameterH;
private $diameterV;
function __construct($diameterH, $diameterV)
{
$this->diameterH = $diameterH;
$this->diameterV = $diameterV;
}
public function output(WidgetInterface $widget)
{
return "ellipse (".$widget->getX().",".$widget->getY().") horizontal diameter=".$this->diameterH.", vertical diameter=".$this->diameterV;
}
}
Rectangle.php
<?php
class Rectangle implements ShapeInterface
{
private $width;
private $height;
function __construct($width,$height)
{
$this->height = $height;
$this->width = $width;
}
/**
* @return mixed
*/
public function getHeight()
{
return $this->height;
}
/**
* @param mixed $height
*/
public function setHeight($height)
{
$this->height = $height;
}
/**
* @return mixed
*/
public function getWidth()
{
return $this->width;
}
/**
* @param mixed $width
*/
public function setWidth($width)
{
$this->width = $width;
}
public function output(WidgetInterface $widget)
{
return "rectangle (".$widget->getX().",".$widget->getY().") width=".
$this->width." height=".$this->height;
}
}
Square.php
<?php
class Square implements ShapeInterface
{
private $size;
function __construct($size)
{
$this->size = $size;
}
/**
* @return mixed
*/
public function getSize()
{
return $this->size;
}
/**
* @param mixed $size
*/
public function setSize($size)
{
$this->size = $size;
}
public function output(WidgetInterface $widget)
{
return "square (".$widget->getX().",".$widget->getY().") size=".$this->size;
}
}
TextBox.php
<?php
class TextBox implements ShapeInterface
{
private $width;
private $height;
private $text;
function __construct($width,$height, $text)
{
$this->height = $height;
$this->width = $width;
$this->text = $text;
}
/**
* @return mixed
*/
public function getHeight()
{
return $this->height;
}
/**
* @param mixed $height
*/
public function setHeight($height)
{
$this->height = $height;
}
/**
* @return mixed
*/
public function getWidth()
{
return $this->width;
}
/**
* @return mixed
*/
public function getText()
{
return $this->text;
}
/**
* @param mixed $text
*/
public function setText($text)
{
$this->text = $text;
}
/**
* @param mixed $width
*/
public function setWidth($width)
{
$this->width = $width;
}
public function output(WidgetInterface $widget)
{
return "textbox (".$widget->getX().",".$widget->getY().") width=".
$this->width." height=".$this->height;
}
}