我现在的想法是有一个多层次的分析对象“层”系统,它在一个公共对象上执行特定的计算,然后根据结果创建一组新的分析对象。然后,新创建的分析对象将轮流运行,并有选择地创建更多分析对象,依此类推。要点是,子分析对象将始终在创建它们的对象之后执行,这一点相对重要。整个装置将由单个线程调用,所以我目前并不关心线程安全。只要满足一定的基本条件,我不认为这是一个不稳定的设计,但我仍然对它有点反胃。
这是一些严重的代码气味,还是我应该继续这样实现它?有没有更好的方法?
下面是一个示例实现:
namespace WidgetTier
{
public class Widget
{
private string _name;
public string Name
{
get { return _name; }
}
private TierManager _tm;
private static readonly Random random = new Random();
static Widget()
{
}
public Widget(string name, TierManager tm)
{
_name = name;
_tm = tm;
}
public void DoMyThing()
{
if (random.Next(1000) > 1)
{
_tm.Add();
}
}
}
//NOT thread-safe!
public class TierManager
{
private Dictionary<int, List<Widget>> _tiers;
private int _tierCount = 0;
private int _currentTier = -1;
private int _childCount = 0;
public TierManager()
{
_tiers = new Dictionary<int, List<Widget>>();
}
public void Add()
{
if (_currentTier + 1 >= _tierCount)
{
_tierCount++;
_tiers.Add(_currentTier + 1, new List<Widget>());
}
_tiers[_currentTier + 1].Add(new Widget(string.Format("({0})", _childCount), this));
_childCount++;
}
//Dangerous?
public void Sweep()
{
_currentTier = 0;
while (_currentTier < _tierCount) //_tierCount will start at 1 but keep increasing because child objects will keep adding more tiers.
{
foreach (Widget w in _tiers[_currentTier])
{
w.DoMyThing();
}
_currentTier++;
}
}
public void PrintAll()
{
for (int t = 0; t < _tierCount; t++)
{
Console.Write("Tier #{0}: ", t);
foreach (Widget w in _tiers[t])
{
Console.Write(w.Name + " ");
}
Console.WriteLine();
}
}
}
class Program
{
static void Main(string[] args)
{
TierManager tm = new TierManager();
for (int c = 0; c < 10; c++)
{
tm.Add(); //create base widgets;
}
tm.Sweep();
tm.PrintAll();
Console.ReadLine();
}
}
}发布于 2010-03-30 20:23:52
Randolpho和LBushkin均为+1。
然而,我仔细考虑了一下,我想我知道为什么会有这种味道。我所实现的模式似乎是Builder模式的某种变态。更好的做法是从一系列分析步骤中创建一个组合,作为一个整体,它代表了某种有意义的状态。分析过程(行为)的每个步骤都应该与输出复合(状态)不同。我在上面实现的东西将状态和行为结合在一起。由于状态持有者和状态分析器是同一个对象,这也违反了单一责任原则。具有复合“构建本身”的方法打开了创建恶性循环的可能性,即使我上面的原型具有确定性完成。
链接:
Builder Pattern
Composite Pattern
发布于 2010-03-30 05:32:01
是的,我把下面的代码称为嗅觉:
_currentTier = 0;
while (_currentTier < _tierCount) //_tierCount will start at 1 but keep increasing because child objects will keep adding more tiers.
{
foreach (Widget w in _tiers[_currentTier])
{
w.DoMyThing();
}
_currentTier++;
} 当集合发生变化时,您正在对它进行迭代。我指的是第一次迭代,而不是第二次。你显然是在解释这个变化(因此是< _tierCount而不是标准的foreach),但它仍然是一种气味,国际海事组织。
我会让它进入生产代码吗?有可能。这取决于场景。但我会对此感到肮脏。
另外:你的_tiers成员可以很容易地成为一个List<List<Widget>>。
发布于 2010-03-30 05:29:32
这里最大的潜在问题是,Sweep方法正在迭代一个集合(_tiers),该集合在调用Widget.DoMyThing()时可能会发生变化。
.NET BCL类不允许在迭代时更改集合。代码的结构方式暴露了可能发生这种情况的风险。
除此之外,另一个问题是程序的结构使得很难理解以什么顺序发生了什么。也许您可以将递归组装模型的程序阶段与访问模型并执行计算的部分分开。
https://stackoverflow.com/questions/2541375
复制相似问题