工厂设计模式; parent = new child()

时间:2017-05-24 05:18:17

标签: c# design-patterns factory

当我使用工厂模式时,当孩子有额外的属性/方法时,我很困惑如何从中创建子类。工厂返回父类型,因为它确定要生成哪个子项,但是当发生这种情况时,我不能像子类一样使用它返回的内容。

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

3 个答案:

答案 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");