我有几个类都继承自同一个Shape
类。当我创建一个新形状时,我希望它是一个随机的形状。我认为这样做的方法是创建一个列表,该列表将保存所有构造函数的链接,当我需要创建一个新形状时,我将从列表中获取一个随机构造函数并使用它来构造我的形状。我试图以最简单的方式创建列表,但是我收到了错误:
List<Action> constList = new List<Action>();
constList.Add(SShape());
constList.Add(OShape());
constList.Add(LShape());
Shape
构造函数定义为:
class Shape
{
public Shape(PlayGrid grid, Color color)
{
...
}
...
}
每个子形状的构造函数定义如下:
class IShape : Shape
{
public IShape(PlayGrid grid, Color color) : base(grid, color)
{
...
}
...
}
构造列表的正确方法是什么,以及从列表中使用构造函数的方法是什么?
承包商还需要获得在不同形状之间变化的参数。
答案 0 :(得分:5)
这个概念可行,您只需要生成委托错误的语法,并且您希望Func<PlayGrid, Color, Shape>
不是Action
:
var constList = new List<Func<PlayGrid, Color, Shape>>();
constList.Add((pg, c) => new SShape(pg, c));
PlayGrid playgrid = /* however you get this */;
Color color = /* however you get this */;
var shape = constList[randomIdx](playgrid, color);
答案 1 :(得分:2)
你可以这样做:
public class ShapeFactory()
{
//list of shape constructor functions
private List<Func<Shape>> constructors;
//static initalizaton of the constructor list
static ShapeFactory()
{
constructors = new List<Func<Shape>>();
constructors.Add( () => new OShape());
constructors.Add( () => new SShape());
constructors.Add( () => new LShape());
....
}
public static Shape CreateRandomShape()
{
int index = ...get random index somehow...
return constructors[index]();
}
}
并在代码
中使用它Shape randomShape = ShapeFactory.CreateRandomShape();
答案 2 :(得分:0)
答案 3 :(得分:0)
以这种方式创建随机对象的责任不应该是对象本身的行为。我建议你create a factory来管理这个。您的工厂可以生成构造函数调用列表(或预缓存对象),然后在其create方法中提供其中一个。您的工厂应返回构造对象(可能作为接口,如IShape),而不是要调用以创建对象的Actions。这样,如果您的工厂需要注入依赖项或设置其他值,它可以这样做并管理对象的构造。
另外,如果那是.NET Action类,我猜你的Shape类不会继承它,但是从你的问题中我不清楚“我得到错误”是什么。
这是关于在基类中使用GetRandomShape()方法的注释。您不希望这样,因为您的基类知道并依赖于其子类,这违反了OO设计实践。
答案 4 :(得分:0)
您可以将类的类型保存到列表中,并使用Activator.CreateInstance(Type)
来获取新实例。
或者您创建一个Shape类型列表,添加每个类的一个实例并使用.Clone()
方法获取新实例。
或者您实施了factory pattern。
答案 5 :(得分:0)
这是你开始的延续。它使用Reflection来调用构造函数。初始列表是类型列表,而不是操作。
class Program
{
static void Main(string[] args)
{
//register the types
List<Type> types = new List<Type>() { typeof(OShape), typeof(PShape), typeof(RShape) };
// randomly select one
Type type = types[1];
// invoke the ctor
ConstructorInfo ctor = type.GetConstructor(/*optional param for ctor, none in this case*/ new Type[] {} );
object instance = ctor.Invoke(new object[] {});
// you can safely cast to Shape
Shape shape = (Shape)instance; //this is a PShape!
}
}
class Shape
{
}
class OShape : Shape
{
}
class PShape : Shape
{
}
class RShape : Shape
{
}
}
接下来要考虑的是如何允许Shape的子类型接收参数。你需要一个工厂模式,即一个知道如何构造其他对象的对象,并将基于 - 例如 - 一个字符串:
Shape s = Factory.GetShape("OShape", new[] object {4});