为了获得最佳的编译时安全,工厂类本身是可以通用的。通过限制泛型定义中的类型,程序总是可以假设只添加(或创建)了正确的类型。
虽然指定构造函数中的类型可以加快创建新的亚型,该检查只能在运行时完成,但有例外
的帮助下通过继承飞机本身,工厂可以调整到特定亚型。 例如具有以下设置:
public abstract class Airplane{}
public abstract class Fighter:Airplane{}
public class F15 : Fighter{}
public class F16 : Fighter{}
public class Boeing747 : Airplane{}
public class AirplaneFactory<T> where T : Airplane
{
List<T> list = new List<T>();
public void Add(T plane) => list.Add(plane); //"Add" used as a general example, but something like "Create" can be used as well. If T itself should be creatable directly, the constraint 'where T: Airplane, new()' can be used
}
下可以使用,最后一行给出一个编译器错误:
var generalFact=new AirplaneFactory<Airplane>();
generalFact.Add(new F15()); //valid
generalFact.Add(new Boeing747()); //valid
var fighterFact = new AirplaneFactory<Fighter>();
fighterFact.Add(new F15()); //valid
fighterFact.Add(new Boeing747()); //Invalid!
因为你可能需要更多的子类,然后继承允许,您可以使用接口。
例如
public interface IAirplane{}
public interface IFighter:IAirplane{}
public interface IVertical:IAirplane{}
public abstract class Airplane:IAirplane{}
public class F15 : Airplane, IFighter{}
public class F16 : Airplane, IFighter{}
public class Boeing747 : Airplane{}
public class F14: Airplane,IFighter,IVertical{}
public class AirplaneFactory<T> where T : IAirplane
{
List<T> list = new List<T>();
public void Add(T plane) => list.Add(plane);
}
并与接口使用工厂:
var generalFact=new AirplaneFactory<IAirplane>();
generalFact.Add(new F15()); //valid
generalFact.Add(new Boeing747()); //valid
var fighterFact = new AirplaneFactory<IFighter>();
fighterFact.Add(new F15()); //valid
var verticalFact=new AirplaneFactory<IVertical>();
verticalFact.Add(new F14()); //valid
verticalFact.Add(new F15()); //Invalid
当然,因为它是一个工厂,创建函数所预期的,而不是“添加”功能。但是对于一个通用的工厂,总是需要额外的规格。
public class AirplaneFactory<T> where T : IAirplane
{
List<T> list = new List<T>();
public void Add(T plane) => list.Add(plane);
public PlaneType Create<PlaneType>()
where PlaneType:class,T,new()
{
var res = new PlaneType();
Add(res);
return res;
}
}
例如
verticalFact.Create<F14>(); //valid
verticalFact.Create<F15>(); //Invalid!
见https://stackoverflow.com/questions/2742276/how-do-i-check-if:但是,这与重用工厂约束的方法来实现-a型是-A-亚型或最类型的-一个对象。我认为这应该有你需要的信息。 – GBreen12
尽管可能不是......我想这不会在技术上“限制”这些类型,它只是让你检查传入的类型。 – GBreen12
同样的问题在这里被问到https://stackoverflow.com/questions/8223073/define-list-of-specific-type-not-object,但是这个问题还没有完全解答。 – 0liveradam8