Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 工厂设计模式;父项=新子项()_C#_Design Patterns_Factory - Fatal编程技术网

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”);可以工作,但我仍然无法访问子属性/方法