在阅读有关ISP的文章时,似乎对ISP有两个相互矛盾的定义:
根据第一定义(见1,2,3),ISP指出,实现该接口的类不应该被迫实施的功能,他们并不需要。因此,胖界面IFat
interface IFat
{
void A();
void B();
void C();
void D();
}
class MyClass: IFat
{ ... }
应该分成较小的接口,ISmall_1
并且ISmall_2
interface ISmall_1
{
void A();
void B();
}
interface ISmall_2
{
void C();
void D();
}
class MyClass:ISmall_2
{ ... }
因为这样我MyClass
能够实现只需要(方法D()
和C()
),而无需被迫还提供了虚拟实现A()
,B()
并且C()
:
但根据第二个定义(见1, 2,通过纳扎尔Merza答案),ISP指出MyClient
调用方法MyService
不应该知道的有关方法MyService
,它不需要。换句话说,如果MyClient
只需要的功能C()
和D()
,然后代替
class MyService
{
public void A();
public void B();
public void C();
public void D();
}
/*client code*/
MyService service = ...;
service.C();
service.D();
我们应该将MyService's
方法隔离到特定于客户端的接口中:
public interface ISmall_1
{
void A();
void B();
}
public interface ISmall_2
{
void C();
void D();
}
class MyService:ISmall_1, ISmall_2
{ ... }
/*client code*/
ISmall_2 service = ...;
service.C();
service.D();
因此,在前者的定义下,ISP的目标是“ 使实现IFat接口的类的寿命变得更容易 ”,而在后者的定义下,ISP的目标是“ 使客户机调用MyService的方法的寿命变得更容易 ”。
ISP的两个不同定义中的哪一个实际上是正确的?
@MARJAN VENEMA
1。
因此,当您要将IFat拆分为较小的接口时,应根据成员的内聚性决定在哪种方法最终决定ISmallinterface。
虽然将聚合方法放在同一个接口中是有意义的,但我认为使用ISP模式时,客户端的需求要优先于接口的“聚合性”。换句话说,我认为与ISP一起,我们应该将特定客户端所需的那些方法集中在同一个接口中,即使这意味着将那些出于凝聚力也应该放在同一个接口中的方法留在该接口之外?
因此,如果有大量的客户,将永远只能需要通话CutGreens
,但不能也GrillMeat
,然后坚持ISP模式,我们应该只把CutGreens
里面ICook
,但也没有GrillMeat
,尽管这两种方法都具有高度凝聚力?
2。
我认为您的困惑源于第一个定义中的一个隐含假设:实施类已经遵循单一责任原则。
通过“实现不遵循SRP的类”,您是指实现的那些类IFat
还是实现ISmall_1
/的类ISmall_2
。我假设您是指实现的类IFat
?如果是这样,为什么您认为他们还没有遵循SRP?
谢谢