工厂模式通常为具体类创建基类,然后具体类从该基类继承。对于很多应用程序,我们需要知道这个工厂可以创建的具体类的数量。例如,工厂创建典型的Shape对象(圆形,矩形等)C#代码示例如下:
public class ShapeFactory
{
public IShape GetShape(int shapeIndex)
{
IShape s = null;
const int color = 1;
const int thickness = 5;
switch (shapeIndex)
{
case 1: s = new Square(color, thickness);
break;
case 2: s = new Triangle(thickness);
break;
case 3: s = new Circle(color);
break;
}
return s;
}
}
用户可能想知道程序支持多少种形状。我知道有两种方法可以做到这一点:
最好的方法是什么?关于这个特定主题的任何最佳实践?
答案 0 :(得分:2)
您可以创建一个为您存储常量的枚举。 这也有助于通过了解“可能性”来帮助用户。通过IDE的自动完成功能,加上它可以防止用户输入数字超出界限的数字。例如进入' 4'在你的例子中。 (请注意,我一般都会写java ...所以C#不是我的强项,但你可以做一些类似于此事的事情)
public class ShapeFactory
{
enum PossibleShapes {CIRCLE,
SQUARE,
TRIANGLE, // c# allows you to do this (extra comma) on constructors, not sure about Enums, and helps with reducing 'bad' line changes in git/etc.
};
public IShape GetShape(PossibleShapes whichShape)
{
IShape s = null;
switch (shapeCode)
{
case PossibleShapes.SQUARE : s = new Square(color, thickness);
break;
case PossibleShapes.TRIANGLE: s = new Triangle(thickness);
break;
case PossibleShapes.CIRCLE: s = new Circle(color);
break;
}
return s;
}
}
"问题"每次添加新的可能性时都必须编辑课程是没有意义的,因为每次这样做时你都必须编辑这个课程,现在你只需要编辑“可能的形状”'也是一类。
(请注意,我仍然不认为这是正确使用工厂模式,因为我不清楚“颜色”和“厚度”值是什么来自,但至少这比使用反射更好)
答案 1 :(得分:1)
这是一个Builder Pattern示例,我认为这是一个更好的示例,为您封装对象创建。 (您可以使用工厂方法模式,而不是为要在构建器中获取的每个形状使用不同的命名方法)
另外,这允许用户轻松设置颜色/厚度(仍然可以有默认值,但我没有将其放入此代码示例中)
表示由构建器
创建的产品public class Shape
{
public Shape()
{
}
public int Color { get; set; }
public int Thickness { get; set; }
}
构建器抽象
public interface IShapeBuilder
{
// Adding NotNull attribute to prevent null input argument
void SetColor([NotNull]string colour);
// Adding NotNull attribute to prevent null input argument
void SetThickness([NotNull]int count);
Shape GetShape();
}
具体构建器实现
public class ShapeBuilder : IShapeBuilder
{
private Shape _shape;
public ShapeBuilder()
{
}
public int GetNumberShapesPossible()
{
//return some # here
}
public void GetSquare(){
this._shape = new Square();
}
public void GetCircle(){
this._shape = new Circle();
}
public void SetColor(string color)
{
this._shape.Color = color;
}
public void SetThickness(int thickness)
{
this._shape.Thickness = thickness;
}
public Shape Build()
{
return this._shape;
}
}
导演
public class ShapeBuildDirector
{
public Shape Construct()
{
ShapeBuilder builder = new ShapeBuilder();
builder.GetCircle();
builder.SetColour(2);
builder.SetThickness(4);
return builder.GetResult();
}
}
当您想要向库中添加新的具体类时,您将不得不在某处更改某些代码。除非你打算将具体类捆绑为某种类型的.dll,但是没有办法解决这个问题。必须对某处的建筑商/工厂/等进行一些编辑。
答案 2 :(得分:0)
您可以将形状类型存储在数组中,然后使用Activator创建实例。它负责索引,计数和简化您的创建功能。
static class ShapeFactory
{
private static readonly Type[] _shapes = new Type[] { typeof(Square), typeof(Triangle), typeof(Circle) };
public static int FactorySize
{
get
{
return _shapes.Length;
}
}
public static IShape GetShape(int shapeIndex, params object[] ctorParams)
{
return (IShape)Activator.CreateInstance(_shapes[shapeIndex], ctorParams);
}
}