Definition: The client should not depend on interfaces it does not require; the dependence of one class on another should be established on the smallest interface.
The problem originates: Class A depends on Class B through interface I, and Class C depends on Class D through interface I. If interface I is not the smallest interface for Class A and Class B, then Class B and Class D must implement methods they do not need.
Solution: Split the bloated interface I into several independent interfaces, and Class A and Class C establish dependencies with the interfaces they need respectively. That is, the principle of interface isolation is adopted.
Let’s give an example to illustrate the principle of interface isolation:
The meaning of this figure is: Class A depends on methods 1, method 2, method 3 in interface I, and Class B is an implementation of dependence on class A. Class C depends on methods 1, method 4, method 5 in interface I, and Class D is an implementation of dependence on class C. For class B and D, although they both have unused methods (that is, methods marked with red fonts in the figure), since interface I is implemented, these unused methods must be implemented.
Let's first look at an example of violating interface isolation:
public interface IWorker { public void work(); public void eat(); } public class Worker implements IWorker{ @Override public void work() { // TODO worker work} @Override public void eat() { // TODO worker eat} } public class Robot implements IWorker { @Override public void work() { // TODO robot work} @Override public void eat() { // TODO robot eat? } }
Since robots do not need to eat, IWorker is considered a bloated interface. Of course, you can also short-term implementation of the eat method in the Robot class, but this may cause unpredictable bugs. For example, if the eat method needs to consume the number of lunch boxes, there will be an incorrect phenomenon.
The following is the modified implementation:
public interface IWorker { public void work(); } public interface IDiet { public void eat(); } public class Worker implements IWorker, IDiet{ @Override public void work() { // TODO work} @Override public void eat() { // TODO work} } public class Robot implements IWorker { @Override public void work() { // TODO robot work} }
Summarize:
1. The interface should be as small as possible and highly cohesive, but it should be appropriate and too detailed and difficult to maintain.
2. If it has been designed as a bloated interface, it can be isolated using adapter mode.