【问题标题】:Abstract factory pattern抽象工厂模式
【发布时间】:2023-07-08 20:03:01
【问题描述】:

我有一个类,CMyDataClass,用来存储数据,它有三个成员变量和两个构造函数,比如

public class CMyDataClass
{
    public String strIndex, strName;
    public int nType;
    public CMyDataClass()
    {
        strIndex = "";
        strName = "";
        nType = 0;
    }
    public CMyDataClass(String ind, String name, int ty)
    {
        strIndex = ind;
        strName = name;
        nType = ty;
    }
}

在另一个类 (CMain) 中,我有一个 List<CMyDataClass>,其中包含两个对象,例如

 List<CMyDataClass> lstMyDataList = new List<CMyDataClass> { new CMyDataClass("", "", 1), 
                                                             new CMyDataClass("", "", 2) };

我有两个继承CMyDataClass 的子类,每个子类都包含一个填充数据结构的函数。

子类中的函数会根据ntype填充对象。

这是我的孩子课程

//Class One

class COne : CMyDataClass
{
    public static bool FillData(CMyDataClass objCMDClass)
    {
        if (objCMDClass.nType == 1)
        {
            objCMDClass.strIndex = "Index-One";
            objCMDClass.strName = "One";
            return true;
        }
        return false;
    }
}



//Class Two

class CTwo : CMyDataClass
{
    public static bool FillData(CMyDataClass objCMDClass)
    {
        if (objCMDClass.nType == 2)
        {
            objCMDClass.strIndex = "Index-Two";
            objCMDClass.strName = "Two";
            return true;
        }
        return false;
    }
}

CMain 类中,我执行子类函数,例如

 public void Func()
    {
        for (int index = 0; index < lstMyDataList.Count; index++)
        {
            if (COne.FillData(lstMyDataList[index]) == false)
                if (CTwo.FillData(lstMyDataList[index]) == false)
                    MessageBox.Show("No data found");
        }
    }

现在的问题是:如果COneCTwo 填充数据对象,它返回一个CMyDataClass 类型的对象。但我需要子类的对象,即如果COne 填充对象,那么对象应该是COne 类型,或者如果CTwo 那么对象应该是 CTwo 对象。

所以我将Child 类更改为

class COne : CMyDataClass
  {
    public static bool FillData(CMyDataClass objCMDClass)
    {
        if (objCMDClass.nType == 1)
        {
            COne obj=new COne();
            obj.strIndex = "Index-One";
            obj.strName = "One";
            objCMDClass=obj
            return true;
        }
        return false;
    }
}

但这不会填充lstMyDataList 中的对象,因为它会创建一个新对象。

如果我的CMyDataClass 是抽象的,我可以使用type cast。但是,如果我将其设为抽象,则无法按如下方式填写lstMyDataList(对象类型未知)。

 List<CMyDataClass> lstMyDataList = new List<CMyDataClass> { new CMyDataClass("", "", 1), new CMyDataClass("", "", 2) };

如何将对象转换为child类型,根据哪个类填充对象?

提前致谢。

【问题讨论】:

    标签: c# design-patterns inheritance abstract-class


    【解决方案1】:

    您不能将对象转换为子类型,因为它不是子类型的实例。 您没有使用继承,而是创建CMyDataClass 的实例,并根据参数以不同方式初始化它们。

    很难说出您到底需要什么或想要什么,鉴于此,这里是否需要继承也不清楚。但如果它是你想要的工厂,它可能是这样的:

        public class CMyDataClass
        {
            // ...snipped definition...
            public CMyDataClass(int type)
            {
                nType = type;
            }        
    
            public virtual void FillData()
            {
            }
    
            static public CMyDataClass Create(int type)
            {
                switch (type)
                {
                    case 1:
                       return new COne(type);
                    case 2:
                       return new CTwo(type);
                    default:
                       return null // or throw an exception, whatever is appropriate
                }
            }
        }
    
        public class COne : CMyDataClass
        {
             public COne(int type)
                 : base(type)
             {
             }
    
             public override void FillData()
             {
                  strIndex = "Index-One";
                  strName = "One";             
             } 
        }
    
        public class CTwo : CMyDataClass
        {
             public CTwo(int type)
                 : base(type)
             {
             }
    
             public override void FillData()
             {
                  strIndex = "Index-Two";
                  strName = "Two";             
             } 
        }
    
    //....
        List<CMyDataClass> lstMyDataList = new List<CMyDataClass> { CMyDataClass.Create(1), 
                                                                     CMyDataClass.Create(2) }
    //....
    
    //....
        public void Func()
        {
            for (int index = 0; index < lstMyDataList.Count; index++)
            {
                lstMyDataList[index].FillData();
            }
        }
    //....
    

    【讨论】:

      【解决方案2】:

      如何将 CMyDataClass 包装在另一个类中,并将新类的实例放入列表框中?然后,您可以在内部拥有 COne 或 CTwo 的实例,具体取决于用于填充它的方法。

      【讨论】: