当我使用工厂模式时,当孩子有额外的属性/方法时,我很困惑如何从中创建子类。工厂返回父类型,因为它确定要生成哪个子项,但是当发生这种情况时,我不能像子类一样使用它返回的内容。
public abstract class Factory
{
public abstract Person getPerson(string type);
}
public class PersonFactory : Factory
{
public override Person getPerson(string type) {
switch (type) {
case "admin":
return new Admin();
case "customer":
return new Customer();
default:
return new Admin();
}
}
}
public abstract class Person
{
public abstract string Type { get; }
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
}
public class Admin : Person
{
private string _securityRole;
public Admin()
{
Id = 0;
}
public override string Type
{
get{
return "admin";
}
}
public string SecurityRole
{
get { return _securityRole; }
set { _securityRole = value; }
}
}
所以我的问题是,当我创建一个PersonFactory对象并决定使用该工厂来创建其他派生类时。我注意到getPerson()返回Person而不是实际输入Admin或Customer。如何让工厂创建子类,使它们实际上是子对象?
Factory pf = new PersonFactory();
Person admin = pf.getPerson("admin");
admin.Id = 1; // is fine
admin.SecurityRole // cannot access
答案 0 :(得分:1)
快速修复就是这个
Admin admin = (Admin)pf.getPerson("admin");
但更好的实施是
1)为您的工厂类使用静态方法。
2)使用通用和接口。
您的新代码将是:
public class PersonFactory //: Factory
{
public static T getPerson<T>() where T: IPerson
{
return Activator.CreateInstance<T>();
}
}
public interface IPerson
{
string Type { get; }
int Id { get; set; }
}
public class Admin : IPerson
{
private string _securityRole;
public Admin()
{
Id = 0;
}
public string Type
{
get
{
return "admin";
}
}
public string SecurityRole
{
get { return _securityRole; }
set { _securityRole = value; }
}
public int Id
{
get;set;
}
}
public class Customer : IPerson
{
private string _securityRole;
public Customer()
{
Id = 0;
}
public string Type
{
get
{
return "customer";
}
}
public string SecurityRole
{
get { return _securityRole; }
set { _securityRole = value; }
}
public int Id
{
get;set;
}
}
以及如何使用:
Admin a = PersonFactory.getPerson<Admin>();
Customer b = PersonFactory.getPerson<Customer>();
答案 1 :(得分:0)
您无法访问该属性的原因是因为您希望此代码行的返回类型为Person
:
Person admin = pf.getPerson("admin");
Person
不包含SecurityRole
的定义。因为您要将返回类型定义为Person
,所以您的结果会有效地转换回Person
对象而不是Admin
对象。
您应该可以通过以下方式解决此问题:
var admin = pf.getPerson("admin");
或使用:
Admin admin = pf.getPerson("admin");
答案 2 :(得分:0)
由于.id
正在运作但不是.SecurityRole
,我认为可以说你创建了一个人而不是管理员。
尝试使用Admin admin = pf.getPerson("admin");
代替Person admin = pf.getPerson("admin");