至少您只让具体类处理克隆,而抽象类具有protected
复制构造函数。现在最重要的是,您希望能够DrawingObject
像这样获取一个变量并克隆它:
class Program
{
static void Main(string[] args)
{
DrawingObject obj1=new Circle(Color.Black, 10);
DrawingObject obj2=obj1.Clone();
}
}
你可能会认为这是作弊,但我会使用扩展方法和反射:
public abstract class DrawingObject
{
public abstract void Draw();
public Color Color { get; set; }
protected DrawingObject(DrawingObject other)
{
this.Color=other.Color;
}
protected DrawingObject(Color color) { this.Color=color; }
}
public abstract class RectangularObject : DrawingObject
{
public int Width { get; set; }
public int Height { get; set; }
protected RectangularObject(RectangularObject other)
: base(other)
{
Height=other.Height;
Width=other.Width;
}
protected RectangularObject(Color color, int width, int height)
: base(color)
{
this.Width=width;
this.Height=height;
}
}
public class Circle : RectangularObject, ICloneable
{
public int Diameter { get; set; }
public override void Draw()
{
}
public Circle(Circle other)
: base(other)
{
this.Diameter=other.Diameter;
}
public Circle(Color color, int diameter)
: base(color, diameter, diameter)
{
Diameter=diameter;
}
#region ICloneable Members
public Circle Clone() { return new Circle(this); }
object ICloneable.Clone()
{
return Clone();
}
#endregion
}
public class Square : RectangularObject, ICloneable
{
public int Side { get; set; }
public override void Draw()
{
}
public Square(Square other)
: base(other)
{
this.Side=other.Side;
}
public Square(Color color, int side)
: base(color, side, side)
{
this.Side=side;
}
#region ICloneable Members
public Square Clone() { return new Square(this); }
object ICloneable.Clone()
{
return Clone();
}
#endregion
}
public static class Factory
{
public static T Clone<T>(this T other) where T : DrawingObject
{
Type t = other.GetType();
ConstructorInfo ctor=t.GetConstructor(new Type[] { t });
if (ctor!=null)
{
ctor.Invoke(new object[] { other });
}
return default(T);
}
}
编辑 1
如果您担心速度(每次都进行反射),您可以 a) 将构造函数缓存在静态字典中。
public static class Factory
{
public static T Clone<T>(this T other) where T : DrawingObject
{
return Dynamic<T>.CopyCtor(other);
}
}
public static class Dynamic<T> where T : DrawingObject
{
static Dictionary<Type, Func<T, T>> cache = new Dictionary<Type,Func<T,T>>();
public static T CopyCtor(T other)
{
Type t=other.GetType();
if (!cache.ContainsKey(t))
{
var ctor=t.GetConstructor(new Type[] { t });
cache.Add(t, (x) => ctor.Invoke(new object[] { x }) as T);
}
return cache[t](other);
}
}