now*_*ed. 5 c# oop interface solid-principles
我正在尝试使用Robert C. Martin原理ISP.
来自维基百科,
该ISP最初是由Robert C. Martin在为Xerox提供咨询时使用和制定的.施乐创建了一个新的打印机系统,可以执行各种任务,如装订和传真.该系统的软件是从头开始创建的.随着软件的发展,修改变得越来越困难,即使是最小的改变也需要一个小时的重新部署周期,这使得开发几乎不可能.
设计问题是几乎所有任务都使用了单个Job类.每当需要执行打印作业或装订作业时,都会对Job类进行调用.这导致了一个"胖"类,其中包含针对各种不同客户的多种方法.由于这种设计,主要作业将知道打印作业的所有方法,即使它们没有用处.
Martin建议的解决方案今天使用了所谓的接口隔离原理.应用于Xerox软件,使用依赖性倒置原则添加了Job类与其客户端之间的接口层.创建了一个Staple Job接口或一个Print Job接口,而不是一个大的Job类,它们分别由Staple或Print类使用,调用Job类的方法.因此,为每个作业类型创建了一个接口,这些接口都是由Job类实现的.
我想要了解的是how the system functioned and what Martin proposed to change it.
interface IJob
{
bool DoPrintJob();
bool DoStaplingJob();
bool DoJob1();
bool DoJob2();
bool DoJob3();
}
class Job : IJob
{
// implement all IJob methods here.
}
var printClient = new Job(); // a class implemeting IJob
printClient.DoPrintJob(); // but `printClient` also knows about DoStaplingJob(), DoJob1(), DoJob2(), DoJob3() also.
Run Code Online (Sandbox Code Playgroud)
我可以尝试到这一点,并坚持到这里
an interface layer between the Job class and its clients was added using the Dependency Inversion Principle - 维基百科行 - (接口层?)
1Instead of having one large Job class, a Staple Job interface or a Print Job interface was created that would be used by the Staple or Print classes, respectively, calling methods of the Job class - (然后调用Job类的方法 - 确定,创建单独的接口,然后为什么要调用job类的方法?)
马丁接下来做了什么?(一些纠正的代码骨架会帮助我理解这一点).
根据答案,我能够如下进行.谢谢谢尔盖和克里斯托斯.
interface IPrintJob
{
bool DoPrintJob();
}
interface IStapleJob
{
bool DoStapleJob();
}
interface IJob : IPrintJob, IStapleJob
{
bool DoPrintJob();
bool DoStaplingJob();
}
var printClient = new PrintJob(); //PrintJob implements the IPrintJob interface
var stapleClient = new StableJob(); // StapleJob implements the IStapleJob interface
Run Code Online (Sandbox Code Playgroud)
太好了.IJob界面做什么,为什么使用它?它可以删除吗?
ISP 不是一种设计模式 - 它是一种设计原则。它有助于避免实现客户端不需要的接口。例如,在您的情况下,您的客户只需要打印。但是您有IJob许多该客户端不需要的方法的接口。如果我只想打印,为什么要实施DoStaplingJob、DoJob1、DoJob2和?DoJob3因此,解决方案是创建满足我的需求的小界面:
public interface IPrintingJob
{
bool DoPrintJob();
}
Run Code Online (Sandbox Code Playgroud)
原始界面将如下所示:
public interface IJob : IPrintingJob
{
bool DoStaplingJob();
bool DoJob1();
bool DoJob2();
bool DoJob3();
}
Run Code Online (Sandbox Code Playgroud)
现在,所有只需要打印的客户端都将实现IPrintginJob接口,而不必担心IJob接口的其他成员。IJob如果您的客户端不需要界面的全部功能,您可以继续将界面拆分为更小的界面IJob。
更新:从客户的角度来看。依赖大接口不是很方便。例如,您的客户只想打印。您可以依赖IJob接口并将Job类实例传递给此客户端:
public void Foo(IJob job)
{
job. // intellisense will show confusing bunch of members you don't need here
}
Run Code Online (Sandbox Code Playgroud)
对于许多小接口,您可以仅依赖于IPrintingJob接口,并且仍然传递大类Job作为该接口的实现:
public void Foo(IPrintingJob printingJob)
{
printingJob. // intellisense will show single member. easy and handy
}
Run Code Online (Sandbox Code Playgroud)
另一个好处是易于重构。稍后您可以将打印功能从Job类中提取到其他小类,例如PrintingJob. 您将能够将其实例传递给仅需要打印的客户端。