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

Han*_*ber 5 oop inheritance design-patterns

我正在设计一个简单的表单创建引擎,用户可以使用各种样板字段类型(Date,Text,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}

        }
}
Run Code Online (Sandbox Code Playgroud)

对于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);
       }
    }
Run Code Online (Sandbox Code Playgroud)

虽然这种设计让我可以自由地独立于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);
       }
Run Code Online (Sandbox Code Playgroud)

小智 1

我认为这两个层次结构之间的差异非常小,您确实应该考虑价值或区别是什么。例如,如果您考虑的是拥有多个具有不同呈现形式的下拉列表控件,那么问问自己,如果不在设计器中,您将在哪里选择具体的控件?

也许您IDropdownListControl可以成为具有抽象“渲染”方法的基类?

你的IFormFieldIControl很相似,我不知道你两个都买什么?

特别是,它IDropDownField看起来确实像 MVC 术语中的模型对象,它与实例化表单时字段将保存的数据有关。这与表单的形成方式无关(您说过它是域模型)。

也许所有人都应该IDropListControls支持该模型IDropDownField?(在这种情况下,我实际上只是删除IDropDownField并直接在 上声明属性IDropListControl)。

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