如何管理(或消除)并行类层次结构?

时间:2011-03-04 23:56:48

标签: oop design-patterns inheritance

我正在设计一个简单的表单创建引擎,用户可以使用各种样板字段类型(日期,文本,DropDown)组合新表单

我决定对域对象(表单字段)进行建模,而不依赖于用于将这些字段呈现给UI的对象。

这是定义域的合同及其某些特化的接口:

namespace Acme.Core.Domain{
    public interface IFormField
            {
                bool Visible { get; set; }
                string Key { get; set; }
                event EventHandler<FieldVisibilityChangedEventArgs> VisibilityChanged;
                FieldType Type{get;}
                void Validate(IEnumerable<ValidationError> errors);
                int DataId {get;set;}
            }

    public interface IDropDownField:IFormField{

                IDictionary<string, string> Items { get; set; }
                KeyValuePair<string, string> SelectedValue { get; set; }

        }
     public interface IDateField:IFormField{

                DateTime? SelectedDate{get;set}

        }
}

对于UI方面,我构建了一个并行类型层次结构。这使得与数据验证有关的业务规则的域对象与UI问题分开,即如何呈现给定字段(MVC HtmlHelper vs WebForm WebControl):

namespace Acme.UI{

        public interface IControl 
        {
                //parallel to IFormField
                bool Visible { get; set; }
                string ID { get; set; }     
        }

        public interface IDropListControl:IControl 
        {
                //parallel to IDropDownField

        }
        public interface IDatePickerControl: IControl 
        {
                //parallel to IDateField

        }

       public interface IControlFactory {

             IControl CreateControl(IFormField field);
       }
    }

虽然这种设计让我可以自由地独立于UI设计域模型,但我还没有找到一种干净的方式来连接和管理这两个层次结构。我觉得我应该能够利用泛型将并行类相互连接起来,但我不能完全理解它的外观。是否有一种模式可以解决关联问题或者完全不需要并行类层次结构?

编辑:我的UI层引用了我的业务层(Core.csproj)。以下是我将UI类层次结构连接到域类层次结构的几个示例。这些类型目前不使用泛型,但我觉得它们应该是。

    // create concrete instances of IControl based on the the domain object passed in 
   public interface IControlFactory {

                 IControl CreateControl(IFormField field);
       }
       // scrape values form the UI controls and apply them to the appropriate domain object
       public interface IFormFieldDataBinder{

                void Bind(IFormField field, IControl control);
       }

1 个答案:

答案 0 :(得分:1)

我认为两个层次结构之间的区别是如此之小,你真的应该考虑价值 - 或 - 区别是什么。例如,如果您正在考虑的是具有不同渲染形式的多个下拉列表控件,那么问问自己,如果不是在设计器中,您将在哪里选择具体控件?

也许你的IDropdownListControl可以是一个带有抽象'Render'方法的基类?

您的IFormFieldIControl非常相似,我不知道您购买的是什么?

IDropDownField特别看起来像MVC术语中的模型对象,它是关于实例化表单时字段所保存的数据。它不是关于表单的形状(你说它是一个领域模型)。

是否所有IDropListControls都支持模型IDropDownField? (在这种情况下,我真的只需删除IDropDownField并直接在IDropListControl上声明属性。

考虑重用抽象原则。对于您创建的每个接口,您能想到两个实现还是它们只是具体的类?