Six principles of design mode (4): interface isolation principle
Definition:The client should not rely on interfaces that it does not need; the dependency of one class on the other class should be built on the smallest interface.
Problem:Class A relies on Class B through interface I, and class C relies 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 the methods they do not need.
Solution:Split bloated interface I into several independent interfaces. Class A and Class C establish dependencies with the interfaces they need. That is, the interface isolation principle is adopted.
For example, describe the interface isolation principle:
(Figure 1 design that does not follow the interface isolation principle)
This figure indicates that Class A depends on method 1, method 2, and method 3 in interface I, and Class B is the implementation of Class A dependency. Method 1, Method 4, and Method 5 in Class C dependency interface I are the implementation of class C dependency. For class B and class D, although they all have methods that are not used (that is, the red font Mark Method in the figure), but because of the implementation of interface I, therefore, these useless methods must also be implemented. If you are not familiar with class diagrams, refer to the program code. The Code is as follows:
Interface I {public void Method1 (); Public void method2 (); Public void method3 (); Public void method4 (); Public void method5 ();} class A {public void depend1 (I I) {I. method1 ();} public void depend2 (I I) {I. method2 ();} public void depend3 (I I) {I. method3 () ;}} Class B implements I {public void Method1 () {system. out. println ("method 1 for Class B implementing interface I");} public void method2 () {system. out. println ("Class B implements interface I Method 2 ");} public void method3 () {system. out. println ("method 3 for Class B to implement interface I");} // For Class B, method4 and method5 are not required, but because interface A has these two methods, // In the implementation process, even if the method bodies of the two methods are empty, the two methods that are ineffective must be implemented. Public void method4 () {} public void method5 () {}} class c {public void depend1 (I I) {I. method1 ();} public void depend2 (I I) {I. method4 ();} public void depend3 (I I) {I. method5 () ;}} Class D implements I {public void Method1 () {system. out. println ("method 1 of class D implementing interface I");} // For Class D, method2 and method3 are not required, but because interface A has these two methods, // In the implementation process, even if the method bodies of the two methods are empty, the two methods that are ineffective must be implemented. Public void method2 () {} public void method3 () {} public void method4 () {system. out. println ("Class D Method 4 for implementing interface I");} public void method5 () {system. out. println ("Class D method for implementing interface I 5") ;}} public class client {public static void main (string [] ARGs) {A = new (); a. depend1 (New B ();. depend2 (New B ();. depend3 (New B (); C = new C (); C. depend1 (new D (); C. depend2 (new D (); C. depend3 (new D ());}}
As you can see, if the interface is too bloated, as long as the methods in the interface appear, no matter whether they are useful to the classes dependent on it, these methods must be implemented in the implementation class, which is obviously not a good design. If you change this design to conform to the interface isolation principle, you must split interface I. Here we split the original interface I into three interfaces. The design 2 after the split is shown as follows:
(Figure 2 Design following the interface isolation principle)
Paste the program code as shown in the following example for your reference:
[Java] view plaincopyinterface I1 {public void Method1 ();} interface I2 {public void method2 (); Public void method3 ();} interface I3 {public void method4 (); public void method5 ();} Class A {public void depend1 (I1 I) {I. method1 ();} public void depend2 (I2 I) {I. method2 ();} public void depend3 (I2 I) {I. method3 () ;}} Class B implements I1, I2 {public void Method1 () {system. out. println ("method 1 for implementing interface I1 in Class B");} public void method2 () {system. out. println ("method 2 for Class B to implement interface I2");} public void method3 () {system. out. println ("method 3 for implementing interface I2 in Class B") ;}} class c {public void depend1 (I1 I) {I. method1 ();} public void depend2 (I3 I) {I. method4 ();} public void depend3 (I3 I) {I. method5 () ;}} Class D implements I1, I3 {public void Method1 () {system. out. println ("method 1 of class D Implementation interface I1");} public void method4 () {system. out. println ("method 4 for Class D to implement interface I3");} public void method5 () {system. out. println ("method of class D implementing interface I3 5 ");}}
The concept of the interface isolation principle is: to create a single interface, do not create a large and bloated interface, and refine the interface as much as possible, as few methods as possible in the interface. That is to say, we need to create a dedicated interface for each class, instead of trying to create a very large interface for all the classes dependent on it to call. In this example, the interface isolation principle is used to change a large interface to three dedicated interfaces. In program design, it is more flexible to rely on several dedicated interfaces than to rely on a comprehensive interface. An interface is a "contract" set for external users during design. Multiple Interfaces can be defined discretely to prevent the spread of external changes and improve the flexibility and maintainability of the system.
Speaking of this, many people will think that the interface isolation principle is very similar to the previous single responsibility principle, but it is not. First, the single responsibility principle originally focuses on duties, while the interface isolation principle focuses on isolation of interface dependencies. Second, a single responsibility principle is mainly a constraint class, followed by interfaces and methods. It is aimed at implementation and details in the program. The interface isolation principle mainly limits interface interfaces and focuses on abstraction, build the overall framework of the program.
When using the interface isolation principle to restrict interfaces, pay attention to the following points:
- The interface should be as small as possible, but limited. Refining the interface can improve the flexibility of the program design. However, if it is too small, it will cause too many interfaces and complicate the design. So be sure to make it moderate.
- To customize services for classes that depend on interfaces, only expose the methods required by the called class, and hide the methods that are not required by the called class. Only by providing customized services for a module can the minimum dependency be established.
- Improve cohesion and reduce external interactions. Make the interface do the most things in the least way.
When using the interface isolation principle, make sure that the interface design is too large or too small. When designing interfaces, you must spend more time thinking and planning to implement this principle accurately.