Читаючи статті про Інтернет-провайдера, схоже, є два суперечливих визначення 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 , відповідь Назара Мерзи ), 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();
Таким чином, колишнє визначення, мета провайдера - " першим полегшити життя класів, що реалізують інтерфейс IFat ", тоді як з останньою метою ISP - " полегшити життя клієнтів, що викликають методи MyService ".
Яке з двох різних визначень провайдера насправді правильне?
@MARJAN VENEMA
1.
Отже, коли ви збираєтеся розділити IFat на менший інтерфейс, які методи в кінцевому підсумку, в якому ISmallinterface слід вирішити, виходячи з того, наскільки згуртовані члени.
Хоча має сенс розміщувати згуртовані методи в одному інтерфейсі, я вважав, що за допомогою шаблону ISP потреби клієнта мають перевагу над "згуртованістю" інтерфейсу. Іншими словами, я подумав, що з ISP ми повинні зв'язати в одному інтерфейсі ті методи, які потрібні певним клієнтам, навіть якщо це означає, що виключати з цього інтерфейсу ті методи, які, заради згуртованості, також повинні бути розміщені всередині того самого інтерфейсу?
Таким чином, якщо було багато клієнтів, яким потрібно буде коли-небудь зателефонувати CutGreens, але не також GrillMeat, тоді дотримуватися шаблону провайдера ми повинні лише вкладати CutGreensвсередину ICook, але не також GrillMeat, хоча ці два методи є дуже згуртованими ?!
2.
Я думаю, що ваша плутанина випливає з прихованого припущення в першому визначенні: що класи-реалізатори вже дотримуються принципу єдиної відповідальності.
Під "реалізацією класів, що не відповідають SRP" ви посилаєтесь на ті класи, які реалізують, IFatабо на класи, які реалізують ISmall_1/ ISmall_2? Я припускаю, що ви маєте на увазі класи, які реалізують IFat? Якщо так, то чому ви вважаєте, що вони вже не дотримуються SRP?
Спасибі