我试图为不将该结构放在下面所示的父BaseModule类中提供一个理由。我更倾向于一种策略模式,并将继承最小化以支持has--一种关系,但我不太确定OOAD的原则是什么--这种模式正在打破。
OOAD的什么原则是打破这种模式?
潜在模式:
public interface IStringRenderer
{
string Render();
}
public class BaseModel : IRequestor
{
public abstract void Init();
public abstract void Load();
}
public class BaseModule<TModel> : IStringRenderer where TModel : BaseModel
{
public TModel Model { get; set; }
public override string Render()
{
return
string.Join(
"",
new string[]
{
"<header/>",
"<main-container>",
"<side-nav>",
"<side-navigation/>",
"</side-nav>",
"<main-content>",
RenderMainContent(),
"</main-content>"
});
}
public abstract string RenderMainContent();
}
public class MyModuleModel : BaseModel
{
public List<int> Ints { get; set; }
...
}
public class MyModule : BaseModule<MyModuleModel>
{
public override string RenderMainContent()
{
return
string.Join(",", Model.Ints.Select(s => s.ToString()).ToArray());
}
}首选模式(重复一些代码以明确):
public interface IStringRenderer
{
string Render();
}
public class BaseModel : IRequestor
{
public abstract void Init();
public abstract void Load();
}
public class MyModuleModel : BaseModel
{
public List<int> Ints { get; set; }
...
}
public class MyModule : IStringRenderer
{
public MyModuleModel Model { get; set; }
public MyModule(MyModuleModel model)
{
this.Model = model;
}
public override string Render()
{
return
string.Join(
"",
new string[]
{
"<header/>",
"<main-container>",
"<side-nav>",
"<side-navigation/>",
"</side-nav>",
"<main-content>",
RenderMainContent(),
"</main-content>"
});
}
public string RenderMainContent()
{
return
string.Join(",", Model.Ints.Select(s => s.ToString()).ToArray());
}
}这个模式中有一些我不想关注的,而是我在想“结构”或者“标签”在哪里。在第一个示例中,它们位于父类中,但在第二个示例中,它们被推入派生类中。
现在,例子非常简单,但是像“侧导航”这样的东西可能会变得很复杂,而且可能需要由孩子来控制。
我觉得这里的原则是,我不觉得‘标记’结构不应该像第一个例子那样出现在父类中。我在我的“首选版本”中还删除了其他一些东西--即泛型。(任何关于这种选择的好/坏的建议都是值得欢迎的)。第一个示例的嵌入式结构的支持者,比如他们可以对大量的子类进行更改。我觉得为派生类提供灵活性是可行的方法,如果需要父类只提供功能和横切功能,但不封装固定结构。
发布于 2013-05-10 11:57:33
你可以兼得这两个世界的优点。在BaseModule<TModel>类中,当您实现(在那里键入override,这是不正确的) Render()方法时,可以将它标记为virtual。这样,需要一组基本标记的子类可以简单地使用基类Render(),而具有更特殊需求的子类可能会覆盖它。
关于泛型,你不能在BaseModule<>中使用它们.除非您在初始化所有派生类的Model属性的构造函数(未显示)中使用它,可能是吗?在这种情况下,它们在这里有它们的用途,因为它们限制了您可以传入的类型,并且它们免除了派生类必须自己初始化它的负担。这更像是一种“框架”方法,其中abstract基类仅用于向派生的具体类提供通用但可覆盖的功能。
发布于 2013-06-09 17:30:33
这听起来类似于CommonClosurePrinciple,但发生在类和方法级别上,而不是包和类级别上。即,
-类-(方法)在发布的组件中-(类)应该共享公共闭包。如果需要更改一个(方法),则可能需要更改所有(方法)。什么影响到一个人,影响到所有人。 (我在括号中添加了这些词)。
此外,从这个代码示例中可以收集到的原则是一个薄弱的原则,这意味着它并不是普遍适用的。显然,在某些情况下,更改不需要/不需要集中到单个类中!
在这个特定的问题中,这个原则的有效性取决于(1) HTML标记和(2)模型到字符串代码在模型发生变化时是否一起被更改。
在这两个版本中,MyModule都是Model和IStringRenderer.Render()之间存在的胶水逻辑的位置。
在第一个版本中,HTML (<main-content>...</>)是由BaseModule提供的服务。
BaseModule类只能使用一次。在第二个版本中,两个胶水逻辑都包含在叶类(MyModule)中:
因此,第二个版本允许将模型呈现和HTML包装代码一起更改。
如果您认为每个模型都需要不同的HTML标记,那么我会说第一个版本是不够的,而第二个版本是不够的。否则,这两个版本都很好。
如果一个人必须为这个原则寻找一个名称,那么它将沿着“.由于同样的原因(更改模型)需要在一起修改的方法,最好放在同一个类中”。
(我强调“会很好”,因为这是一个薄弱的原则,或者说,一个经验法则,而不是一个真正的原则。)
它听起来类似于CommonClosurePrinciple,但应用于类和方法级别,而不是包和类级别。
https://softwareengineering.stackexchange.com/questions/197584
复制相似问题