我有两个类,Server和Client。服务器需要在多个线程中实例化Client,而Client有一个需要提供自定义实现的虚拟成员。我的问题是。 Client类应该是Server类的嵌套类,还是应该使用Interface和Dependency Injection将自定义实现引入Server类。现在,Client类还有许多私有方法,它们提供了一些不应更改的标准逻辑。
public class Server
{
public void DoWork()
{
for (var i = 0;i < 10; i++)
{
Client client = new Client();
client.Process(i);
}
}
}
public class Client
{
private void doSomething()
{
...
}
// Needs to be overridden and provide custom logic
public virtual string Process(int i)
{
return i.ToString();
}
}
工作示例:
public interface IClient
{
string Process(string message);
}
public abstract class Client : IClient
{
public virtual string Process(string message)
{
return message;
}
}
public class CustomClient : Client
{
public CustomClient() { }
public override string Process(string message)
{
return string.Format("Custom Client:{0}", message);
}
}
public class Server
{
private Func<IClient> createClient;
public Server() { }
public Server(Func<IClient> client)
{
createClient = client;
}
public void DoWork()
{
for (var i = 0; i < 10; i++)
{
IClient = client = createClient();
client.Process(string.Format("Client #{0}", i));
}
}
}
测试程序......你会逐步看到它点击CustomClient
class Program
{
static void Main(string[] args)
{
Func<CustomClient> factory = () => new CustomClient();
var server = new Server(factory);
server.DoWork();
}
}
答案 0 :(得分:1)
是否应该注入或修复依赖关系的问题有一个简单的答案 - 提供逻辑的类是一个需要注入的候选者。另一方面,如果您不打算更改逻辑,则可以像对大多数基类库一样对固定类型进行编码。
您所描述的内容听起来像DI的场景 - 如果您允许覆盖客户端类,那么您认为可以进行更改。 DI是同时处理依赖和变化的最明显的方法之一。
答案 1 :(得分:1)
如果服务器需要创建客户端,我会将工厂方法传递给服务器以供其使用。所以我会去依赖注入。
例如:您可以将Server
构造函数传递给Func<IClient>
并将其分配给名为createClient
的私有字段,然后代替
Client client = new Client();
使用
IClient client = createClient();
这样你就可以完全解耦服务器和客户端。
我更喜欢使用简单的Func
委托而不是完整的工厂类,因为这是(a)更容易使用和(b)更松散耦合。