سؤال

ما هو وسيلة أكثر أناقة من وجود رمز أدناه حيث أريد للعودة إلى فئة مشتقة بناء على نوع من فئة أخرى.

            if (option_ is Rectangle)
            {
                modelInputs = new Foo();
            }
            else if (option_ is Circle)
            {
                modelInputs = new Bar();
            }
            else if (option_ is Triangle)
            {
                modelInputs = new Bar2();
            }
هل كانت مفيدة؟

المحلول

هل لديك مستطيل، دائرة ومثلث تنفيذ IHasModelInput:

interface IHasModelInput
{
    IModelInput GetModelInput();
}

وبعد ذلك يمكنك القيام به

IModelInput modelInputs = option_.GetModelInput();

نصائح أخرى

ورأيي: طريقك "ائقة" على ما يرام. انها بسيطة، قابلة للقراءة ولا وظيفة.

وبعد أن مستطيل، دائرة ومثلث تنفيذ وظيفة مصنع اللازمة عبر <ط> IHasModelInput سيعمل، لكنه لا يملك تكاليف تصميم: كنت قد يقترن الآن هذه المجموعة من الطبقات مع مجموعة IModelInput الطبقات ( فو، بار وBar2). ويمكن أن تكون في مكتبتين مختلفة تماما، وربما لا ينبغي أن تعرفه عن بعضها البعض.

وهناك طريقة أكثر تعقيدا أدناه. فهو يوفر لك ميزة كونها قادرة على تكوين منطق المصنع الخاص بك في وقت التشغيل.

    public static class FactoryMethod<T>  where T : IModelInput, new()
    {
        public static IModelInput Create()
        {
            return new T();
        }
    }

    delegate IModelInput ModelInputCreateFunction();

    IModelInput CreateIModelInput(object item)
    {

        Dictionary<Type, ModelInputCreateFunction> factory = new Dictionary<Type, ModelInputCreateFunction>();


        factory.Add(typeof(Rectangle), FactoryMethod<Foo>.Create);
        factory.Add(typeof(Circle),    FactoryMethod<Bar>.Create);
        // Add more type mappings here




        IModelInput modelInput;
        foreach (Type t in factory.Keys)
        {
            if ( item.GetType().IsSubclassOf(t) || item.GetType().Equals(t))
            {
                modelInput = factory[t].Invoke();
                break;
            }
        }
        return modelInput;
    }

ولكن بعد ذلك نطرح هذا السؤال: أي واحد تفضل أن تقرأ

هل يمكن وضع المدخلات والمخرجات في جدول هاش، أو تخزين أنواع التي تخلق كل فئة داخل كل واحد من الطبقات إنشاء ثم استخدام Activator.CreateInstance للقيام factoryin ':

Hashtable ht = new Hashtable();
ht.Add(typeof(Rectangle), typeof(Bar));
ht.Add(typeof(Square), typeof(Bar2));

modelInputs = Activator.CreateInstance(ht[option.GetType()]);

وفي كلتا الحالتين، Activator.CreateInstance هو وسيلة باردة جدا لجعل المصانع تعمل في .NET. التمتع، واستخدام القوة أعطيتكم بحكمة، والابن.

هل يمكن ربط نوع مع "option_"، إذا كان يسمح، وبعد ذلك فقط إنشاء مثيل له.

وعادة ما تستخدم طريقة مصنع مثل هذا عندما كنت ترغب في تحويل السلسلة إلى نوع في وقت التشغيل، وأنا استخدم قاموس تعين سلسلة إلى نوع.

ومثل هذا من مشروع حديث:

public class TaskFactory
{
    private Dictionary<String, Type> _taskTypes = new Dictionary<String, Type>();

    public TaskFactory()
    {
        // Preload the Task Types into a dictionary so we can look them up later
        foreach (Type type in typeof(TaskFactory).Assembly.GetTypes())
        {
            if (type.IsSubclassOf(typeof(CCTask)))
            {
                _taskTypes[type.Name.ToLower()] = type;
            }
        }
    }

    public CCTask CreateTask(XmlElement task)
    {
        if (task != null)
        {
            string taskName = task.Name;
            taskName =  taskName.ToLower() + "task";

            // If the Type information is in our Dictionary, instantiate a new instance of that task
            Type taskType;
            if (_taskTypes.TryGetValue(taskName, out taskType))
            {
                return (CCTask)Activator.CreateInstance(taskType, task);
            }
            else
            {
                throw new ArgumentException("Unrecognized Task:" + task.Name);
            }                               
        }
        else
        {
            return null;
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top