- Abstraction
public interface IService
{
void DoFavor1();
void DoFavor2();
}
public interface IClient
{
void DoSomeMagic1(IService serviceProvider); // implementation will use serviceProvider parameter to call DoFavor* methods
void DoSomeMagic2(IService serviceProvider); // implementation will use serviceProvider parameter to call DoFavor* methods
}
In this approach, service should be injected into client caller (so client caller can pass it as argument).
- Abstraction
public interface IService
{
void DoFavor1();
void DoFavor2();
}
public interface IClient
{
void DoSomeMagic1();
void DoSomeMagic2();
}
- Concrete
private readonly IService _serviceProvider; // will call DoFavor* methods in DoSomeMagic* implementations
public RealClient(IService serviceProvider)
{
_serviceProvider = serviceProvider;
}
In this approach, client can use it at any time privately, but, think of a new method at IService (ex. DoFavor3();
) which might not be used at all by the client, then how client caller can call DoFavor3();
? In this case, the service should be passed to client caller again!!
- Abstraction
public interface IService
{
void DoFavor1();
void DoFavor2();
}
public interface IClient
{
IService ServiceProvider { get; }
void DoSomeMagic1();
void DoSomeMagic2();
}
- Concrete
// Usages:
// 1. DoSomeMagic* implementations,
// 2. ANYWHERE OUTSIDE THE CONCRETE, EX: realClient.ServiceProvider.DoFavor1()
public IService ServiceProvider { get; }
public RealClient(IService serviceProvider)
{
ServiceProvider = serviceProvider;
}
In this approach, client can use the service internally, and client caller can use the service directly. I liked it!