You should encapsulate this into SimpleShapeFactory
.
If you don't want to write if
or case
, you could create your own Attribute
(let name it ShapeNameAttribute
):
[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = false)]
sealed class ShapeNameAttribute : Attribute
{
#region Constructors
public ShapeNameAttribute(string name)
{
Name = name;
}
#endregion // Constructors
#region Properties
public string Name
{
get;
set;
}
#endregion // Properties
}
Then mark all your classes with this attribute:
[ShapeName("Shape")]
public class Shape
{
}
[ShapeName("Circle")]
class Circle : Shape
{
}
[ShapeName("Triangle")]
class Triangle : Shape
{
}
And create SimpleShapeFactory
like this:
static class SimpleShapeFactory
{
#region Private Members
public static readonly Type[] _shapes = new Type[]
{
typeof(Shape),
typeof(Circle),
typeof(Triangle)
};
#endregion // Private Members
#region Methods
/// <summary>
/// Creates shape by it's name
/// </summary>
/// <param xmlName="name">Name of the shape</param>
/// <returns>Created shape</returns>
public static Shape Create(string name)
{
foreach(var shape in _shapes)
{
var attribute = (ShapeNameAttribute)shape.GetCustomAttributes(typeof(ShapeNameAttribute), true)[0];
if(attribute.Name == name)
{
return (Shape)Activator.CreateInstance(shape);
}
}
throw new ArgumentException("Invalid name");
}
#endregion // Methods
}
If you don't want to define allowed types in SimpleShapeFactory
, you could, of course, use reflection to determine their, but
Note: Always remember, using reflection may cause performance problems.