C# 工厂设计模式;父项=新子项()
当我使用工厂模式时,我不知道当子模式有额外的属性/方法时如何从中生成子类。工厂在计算要生成哪个子类时返回父类型,但当这种情况发生时,我不能像使用子类一样使用它返回的内容C# 工厂设计模式;父项=新子项(),c#,design-patterns,factory,C#,Design Patterns,Factory,当我使用工厂模式时,我不知道当子模式有额外的属性/方法时如何从中生成子类。工厂在计算要生成哪个子类时返回父类型,但当这种情况发生时,我不能像使用子类一样使用它返回的内容 public abstract class Factory { public abstract Person getPerson(string type); } public class PersonFactory : Factory { public override Person getP
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
无法访问该属性的原因是,您希望此行代码的返回类型为
Person
:
Person admin = pf.getPerson("admin");
Person
不包含SecurityRole
的定义。由于您将返回类型定义为Person
,因此您的结果将有效地回溯到Person
对象,而不是Admin
对象
您应该能够通过以下方式解决此问题:
var admin = pf.getPerson("admin");
或使用:
Admin admin = pf.getPerson("admin");
由于
.id
正在工作,但不是.SecurityRole
我认为可以肯定地说,你创造了一个人而不是管理员
尝试Admin Admin=pf.getPerson(“Admin”)代码>而不是Person admin=pf.getPerson(“admin”)代码>这是一个快速解决方案
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;
}
}
公共类PersonFactory/:Factory
{
公共静态T getPerson(),其中T:IPerson
{
返回Activator.CreateInstance();
}
}
公共接口IPerson
{
字符串类型{get;}
int Id{get;set;}
}
公共类管理员:IPerson
{
私有字符串_securityRole;
公共管理()
{
Id=0;
}
公共字符串类型
{
得到
{
返回“admin”;
}
}
公共字符串安全
{
获取{return\u securityRole;}
设置{u securityRole=value;}
}
公共整数Id
{
获得;设置;
}
}
公共类客户:IPerson
{
私有字符串_securityRole;
公众客户()
{
Id=0;
}
公共字符串类型
{
得到
{
返回“客户”;
}
}
公共字符串安全
{
获取{return\u securityRole;}
设置{u securityRole=value;}
}
公共整数Id
{
获得;设置;
}
}
以及如何使用:
Admin a = PersonFactory.getPerson<Admin>();
Customer b = PersonFactory.getPerson<Customer>();
Admin a=PersonFactory.getPerson();
客户b=PersonFactory.getPerson();
看看这段代码,我想知道管理员是否真的应该是一个人——也许它应该是一个人的“角色”。我意识到,这段代码可能来自教程或其他东西,但如果是生产代码,我会考虑到LISKOV替代原则,并考虑这是否违反了它。Admin=pf.getPerson(“Admin”);似乎不起作用,无法将Person隐式转换为Admin。我认为该方法想要返回一个人。Person admin=new Person;--Admin realAdmin=Admin.getPerson(“Admin”);尽管在这一点上,首先应该质疑这是否是正确的设计模式。var admin=pf.getPerson(“admin”);可以工作,但我仍然无法访问子属性/方法