免责声明:我很乐意在此使用dependency injection 项目并且全面地采用基于接口的松散耦合设计,但在该项目中使用了依赖注入。另外SOLID设计原则(以及design patterns一般而言)是我工作的外国人,我自己也是很多人。所以把它带入 在建议更好地设计这个问题时要考虑。
这是我正在处理的代码的简化版本,因此它可能看起来很人为。如果是这样,我道歉。请考虑以下类:
// Foo is a class that wraps underlying functionality from another
// assembly to create a simplified API. Think of this as a service layer class,
// a facade-like wrapper. It contains a helper class that is specific to
// foo. Other AbstractFoo implementations have their own helpers.
public class Foo : AbstractFoo
{
private readonly DefaultHelper helper;
public override DefaultHelper Helper { get { return helper; } }
public Foo()
{
helper = new Helper("custom stuff");
}
public override void Operation1(string value)
{
Console.WriteLine("Operation1 using " + value);
}
public override void Operation2()
{
Console.WriteLine("Operation2");
}
}
// Helper derives from a default implementation and allows us to
// override it's methods to do things specific for the class that
// holds this helper. Sometimes we use a custom helper, sometimes
// we use the default one.
public class Helper : DefaultHelper
{
private readonly string customStuff;
public Helper(string value)
{
customStuff = value;
}
public override void DoSomethingHelpful()
{
Console.WriteLine("I was helpful using " + customStuff);
}
}
假设这两个类使用如下:
// foo referenced and used in one part of code
var foo = new Foo();
foo.Operation2(); // or foo.Operation1();
// some other point in the program where we don't have a reference to foo
// but do have a reference to the helper
helper.DoSomethingHelpful();
但是我现在发现我还需要在foo.Operation1
的某些实现中执行helper.DoSomethingHelpful();
?我想到的潜在解决方法是:
Action<string>
委托传递给Helper的构造函数。这些方法似乎都不是理想的(虽然我已经确定我不喜欢选项1 而且如果我们担心选项3 的可维护性稍后发现我们需要传递更多的代表)。这让我想知道Helper
/ Foo
组合的初始设计是否存在问题。想法?
答案 0 :(得分:3)
休闲(“使用”)关系怎么样:
public class Helper : DefaultHelper
{
private readonly string customStuff;
public Helper(string value)
{
customStuff = value;
}
public override void DoSomethingHelpful(AbstractFoo foo)
{
foo.Operation1();
Console.WriteLine("I was helpful using " + customStuff);
}
}
因此,您需要修改抽象帮助器以期望引用正确的Foo
实现。
答案 1 :(得分:1)
我认为你有你需要的东西。尽量不要设计“以防我以后需要它”并且不要修复没有破坏的东西。如果将来你需要从你的帮助器中使用Operation1,然后将它作为构造函数的依赖项(如你所建议的那样)添加,或者只是将它传递给你正在调用的方法。这取决于场景,当你真正需要的时候你就会拥有它。
编辑:改变了“尽量不设计未来”,因为它似乎不是我想说的。
再次编辑问题中的相应更改
你可以这样:
helper.DoSomethingUsefulWith( foo );
所以你的帮助方法将获得工作所需的依赖
答案 2 :(得分:1)
“这些方法似乎都不是理想的(虽然我已经很多了 确定我不喜欢选项1,我担心可维护性 如果我们稍后发现我们需要传递更多的代表,则使用选项3)。 这让我想知道初始设计是否存在问题 Helper / Foo组合。“
你说得对 - Helper和Foo的设计存在问题。您最初描述的基本Foo / Helper关系很好,当您必须包装您无法控制的其他对象时,这是一种常见的模式。但是你说:
“如果我发现我还需要在某些内容中执行foo.Operation1该怎么办? helper.DoSomethingHelpful();?“
的实现
这是我们遇到问题的地方。你开始描述Foo依赖于Helper的关系;现在你正在描述Helper依赖于Foo的关系。这立刻告诉我你的依赖关系纠缠不清。对象之间的依赖关系应该只采用一种方式;实际上依赖注入依赖于此。
答案 3 :(得分:1)
我认为你所有的解决方案都很好;他们只是提供不同的能力。这些差异现在不是太重要,但可能在未来。
你更喜欢第二个,你的直觉是这里最好的指导,你比我们其他人更了解你的代码的未来。我最喜欢你的第二个解决方案,因为它摆脱了一个类并且更简单。由于它的简单性,如果你以后必须做其他事情,你就不会丢掉很多工作。
第一种方法允许您使用不同的Helper(IHelper?)实例和子类来玩游戏。最后一种方法为Helper增加了很多灵活性。 (虽然它可能会增加很多,但你不需要帮助,只需要你传递给它的方法。)如果要么解决更多未来的问题,你可以转用它们。问题。