超拼科技接口隔离原则 (ISP)详解

作者: CarlLee 分类: 技术方案 发布时间: 2022-05-29 23:10

当我们设计一个应用程序时,我们应该注意我们将如何抽象一个包含多个子模块的模块。考虑到类实现的模块,我们可以在接口中完成系统的抽象。但是如果我们想扩展我们的应用程序,添加一个只包含原始系统的一些子模块的模块,我们就不得不实现完整的接口并编写一些虚拟方法。这样的接口称为胖接口或污染接口。界面污染不是一个好的解决方案,可能会导致系统出现不适当的行为。

接口隔离原则指出不应强迫客户端实现他们不使用的接口。代替一个胖接口,许多基于方法组的小接口是首选的,每个接口服务一个子模块。

例子

面是一个违反接口隔离原则的例子。我们有一个 Manager 类,它代表管理工人的人。我们有两种类型的工人,一些是普通工人,一些是非常高效的工人。两种类型的工人都工作,他们需要每天休息时间吃饭。但是现在一些机器人进入了他们工作的公司,但他们不吃东西,所以他们不需要发射休息。一方面,新的 Robot 类需要实现 IWorker 接口,因为 robots 可以工作。另一方面,他们不必实施它,因为他们不吃东西。

这就是为什么在这种情况下 IWorker 被认为是污染接口。

如果我们保持目前的设计,新的 Robot 类将被迫实现eat 方法。我们可以编写一个什么都不做的虚拟类(假设每天有 1 秒的启动中断),并且可能对应用程序产生不良影响(例如,经理看到的报告会报告吃的午餐比人数多)。

根据接口隔离原则,灵活的设计不会有污染的接口。在我们的例子中,IWorker 接口应该分成 2 个不同的接口。

// interface segregation principle - bad example
interface IWorker {
	public void work();
	public void eat();
}

class Worker implements IWorker{
	public void work() {
		// ....working
	}
	public void eat() {
		// ...... eating in launch break
	}
}

class SuperWorker implements IWorker{
	public void work() {
		//.... working much more
	}

	public void eat() {
		//.... eating in launch break
	}
}

class Manager {
	IWorker worker;

	public void setWorker(IWorker w) {
		worker=w;
	}

	public void manage() {
		worker.work();
	}
}

接下来是支持接口隔离原则的代码。通过将 IWorker 接口拆分为 2 个不同的接口,新的 Robot 类不再被迫实现 eat 方法。此外,如果我们需要机器人的其他功能,例如充电,我们将创建另一个接口 IRechargeble 并使用方法重新充电。

// interface segregation principle - good example
interface IWorker extends Feedable, Workable {
}

interface IWorkable {
	public void work();
}

interface IFeedable{
	public void eat();
}

class Worker implements IWorkable, IFeedable{
	public void work() {
		// ....working
	}

	public void eat() {
		//.... eating in launch break
	}
}

class Robot implements IWorkable{
	public void work() {
		// ....working
	}
}

class SuperWorker implements IWorkable, IFeedable{
	public void work() {
		//.... working much more
	}

	public void eat() {
		//.... eating in launch break
	}
}

class Manager {
	Workable worker;

	public void setWorker(Workable w) {
		worker=w;
	}

	public void manage() {
		worker.work();
	}
}

结论

如果设计已经完成,胖接口可以使用适配器模式进行隔离。

像每个原则一样,接口隔离原则是一项原则,需要在设计时花费额外的时间和精力来应用它并增加代码的复杂性。但它产生了灵活的设计。如果我们要应用它超出必要的范围,它将导致代码包含许多具有单一方法的接口,因此应根据经验和常识来确定代码扩展更可能发生的区域未来。