我一次又一次地沿着这些行编写代码,在那里我创建了一些对象,然后循环遍历它们以使用另一个类初始化一些属性......
ThingRepository thingRepos = new ThingRepository();
GizmoProcessor gizmoProcessor = new GizmoProcessor();
WidgetProcessor widgetProcessor = new WidgetProcessor();
public List<Thing> GetThings(DateTime date)
{
List<Thing> allThings = thingRepos.FetchThings();
// Loops through setting thing.Gizmo to a new Gizmo
gizmoProcessor.AddGizmosToThings(allThings);
// Loops through setting thing.Widget to a new Widget
widgetProcessor.AddWidgetsToThings(allThings);
return allThings;
}
......这只是,感觉不对。
<小时/> 修改:假设
GizmoProcessor
和WidgetProcessor
都必须关闭并进行一些计算,并从其他表中获取一些额外的数据。它们不仅仅是存储在存储库中的数据。他们根据每个Thing
创建新的Gizmo和Widgets,并将它们分配给Thing
的属性。
这对我来说很奇怪的原因是Thing
不是一个自治对象;它无法创建自己和子对象。它需要更高级的代码来创建完全完成的对象。我不确定这是不是坏事!
答案 0 :(得分:1)
ThingRepository
应该是获取Thing
集合的单一访问点,或者至少是开发人员直观看待的集合。出于这个原因,GetThings(DateTime date)
应由另一个对象提供,这感觉很奇怪。我宁愿把这个方法放在ThingRepository
本身。
Thing
返回的GetThings(DateTime date)
不同,ThingRepository.FetchThings()
返回的动物比“{1}}返回的动物更胖”也感觉很尴尬和反直觉。如果Gizmo
和Widget
确实是Thing
实体的一部分,那么每当您拥有Thing
实例时,您应该能够访问它们,而不仅仅是针对返回的实例GetThings(DateTime date)
。
如果GetThings()
中的日期参数不重要或可以在其他时间收集,我会使用Thing
上的计算属性来实现对Gizmo
和{的按需访问{1}}:
Widget
请注意,只要执行的计算成本太高,此方法就有效。不推荐使用昂贵处理的计算属性 - 请参阅http://msdn.microsoft.com/en-us/library/bzwdh01d%28VS.71%29.aspx#cpconpropertyusageguidelinesanchor1
但是,这些计算不必在getter中内联实现 - 它们可以委托给第三方Gizmo / Widget处理器,可能还有缓存策略等。
答案 1 :(得分:1)
如果您有复杂的初始化,那么您可以使用策略模式。以下是根据this strategy pattern overview
改编的快速概述创建一个策略界面来抽象初始化
public interface IThingInitializationStrategy
{
void Initialize(Thing thing);
}
策略可以使用的初始化实现
public class GizmosInitialization
{
public void Initialize(Thing thing)
{
// Add gizmos here and other initialization
}
}
public class WidgetsInitialization
{
public void Initialize(Thing thing)
{
// Add widgets here and other initialization
}
}
最后是一个以抽象方式接受策略实现的服务类
internal class ThingInitalizationService
{
private readonly IThingInitializationStrategy _initStrategy;
public ThingInitalizationService(IThingInitializationStrategy initStrategy)
{
_initStrategy = initStrategy;
}
public Initialize(Thing thing)
{
_initStrategy.Initialize(thing);
}
}
然后您可以使用像这样的初始化策略
var initializationStrategy = new GizmosInitializtion();
var initializationService = new ThingInitalizationService(initializationStrategy);
List<Thing> allThings = thingRepos.FetchThings();
allThings.Foreach ( thing => initializationService.Initialize(thing) );
答案 2 :(得分:0)
唯一真正的潜在问题是你在同一个循环中多次迭代,但如果你需要点击一个数据库来获取所有小玩意和小部件,那么批量请求它们可能会更有效率您的Add ...方法的完整列表是有意义的。
另一个选择是在第一个存储库调用中调用返回gizmo和小部件(假设它们位于同一个repo中)。它可能会使查询更复杂,但它可能会更有效。当然,除非您在获取东西时总是不需要获取小玩意和小部件。
答案 3 :(得分:0)
回答你的问题:
这是个坏主意吗?
我在这里使用的是反模式的名称吗?
有哪些替代方案?
就个人而言,我会编写代码:
public List<Thing> GetThings(DateTime date)
{
List<Thing> allThings = thingRepos.FetchThings();
// Build the gizmo and widget for each thing
foreach (var thing in allThings)
{
thing.Gizmo = gizmoProcessor.BuildGizmo(thing);
thing.Widget = widgetProcessor.BuildWidget(thing);
}
return allThings;
}
我的理由是:
Thing
的属性。Thing
的任何属性。但是,如果您的处理器类一次构建多个属性,那么我只会将属性初始化重构为每个处理器。
public List<Thing> GetThings(DateTime date)
{
List<Thing> allThings = thingRepos.FetchThings();
// Build the gizmo and widget for each thing
foreach (var thing in allThings)
{
// [Edited]
// Notice a trend here: The common Initialize(Thing) interface
// Could probably be refactored into some
// super-mega-complex Composite Builder-esque class should you ever want to
gizmoProcessor.Initialize(thing);
widgetProcessor.Initialize(thing);
}
return allThings;
}
P.S:
[编辑]
注意到已经就使用战略服务给出了答案。