Interface separation principle

  • The refinement of some large interfaces into smaller ones is available, that is, multiple specific client interfaces are better than one general interface.
  • Note, however, that the granularity of interfaces should not be too small. If it is too small, the number of interfaces will be too many and the design will be complicated

advantages

  • Avoid the method that the same interface contains different kinds of responsibilities, and the interface responsibility division is more clear, in line with the idea of high cohesion and low coupling.

The code on

  • Let’s illustrate the interface isolation principle using the example of a car

Demand point

  • A car can run, brake, accelerate, airbag, burn gas.
  • An electric car can run, brake, accelerate, airbag, use electricity.

Bad design

  • The proxy puts capabilities into a class as interfaces.
------------ NormalCarProtocol.h ------------- @protocol NormalCarProtocol <NSObject> - (void)run; // Run - (void)brake; // Brake - (void)speed; // Accelerate - (void)safeAirCell; //@optional - (void)useGasoline; // (void)useElectricPower; / / electricity @ the endCopy the code
  • Ordinary cars abide by the agreement
-- -- -- -- -- -- -- -- average car -- -- -- -- -- - must keep the agreement @ interface NormalCar: NSObject<NormalCarProtocol> @end ----- Implementation of the protocol ----- @implementation NormalCar - (void)run{NSLog(@" run "); } - (void)brake{NSLog(@" brake "); } - (void)speed{NSLog(@" speed "); } - (void)safeAirCell{NSLog(@" airbag "); } - (void)useGasoline{NSLog(@" useGasoline "); } - I have this protocol capability but I don't want to implement it - (void)useElectricPower{return; } @endCopy the code
  • The electric car
----- Electric vehicles ---- also adhere to this agreement @interface Electrocar: NSObject<NormalCarProtocol> @implementation Electrocar - (void)run{NSLog(@" run "); } - (void)brake{NSLog(@" brake "); } - (void)speed{NSLog(@" speed "); } - (void)safeAirCell{NSLog(@" airbag "); } - The ability to use gasoline is disabled. - (void)useGasoline{ return; } - (void)useElectricPower{NSLog(@" use power "); } @endCopy the code

We found that not all cars are required to implement all methods in NormalCarProtocol. Because of the redundancy caused by the design of the interface method, the design does not comply with the principle of interface isolation.

Good design

  • Separate the connection between electricity and gas into a separate protocol
@protocol PowerProtocol <NSObject> - (void)Power; // Power @end - Make the car comply with two protocols @interface NormalCar: NSObject < NormalCarProtocol PowerProtocol > method to realize Power -- -- -- -- -- -- - (void) Power {NSLog (@ "petrol"); } @ interface Electrocar: NSObject < NormalCarProtocol PowerProtocol > method to realize Power -- -- -- -- -- -- - (void) Power {NSLog (@ "electricity"); }Copy the code

Because we separate the interfaces of different responsibilities, the responsibilities of the interfaces are more clear and concise. Different cars can be implemented in their own way according to their own needs, following the required interface.

And in the future, if there are other functions, such as music-related methods, a protocol can be added to avoid interface overcrowding and improve the cohesion of the program. Add a music protocol for both cars to keep the protocol complete function. # think

  • Now there’s an old man’s scooter with no music playing.
  • Is it three agreements for cars, three agreements for electric cars, and two agreements for scooters? Implement the methods in the protocol separately.

UML class diagram comparison

  • Interface separation principle not practiced: having invalid methods

  • The interface separation principle is practiced:

By adhering to the principle of interface separation, interface design becomes more concise, and the various client classes do not need to implement interfaces that they do not need to implement.

How to practice

  • When designing interfaces, and especially when adding methods to existing interfaces, we need to carefully consider whether these methods address the same kind of task: if so, they can be put together; If not, you need to split it.

  • Those of you doing iOS development should be familiar with the UITableViewDelegate and UITableViewDataSource protocols.

  • The methods in both protocols are UITableView related, but the iOS SDK designers put these methods in two different protocols. The reason is that the two protocols contain methods that handle different kinds of tasks:

  • UITableViewDelegate: Contains methods that an instance of a UITableView tells its proxy of some click event, that is, the event is passed from the instance of the UITableView to its proxy.

  • UITableViewDataSource: The method that contains the UITableView’s delegate to the UITableView is the transfer of data necessary for the UITableView to display.

  • Obviously, the designers of the UITableView protocol have implemented the principle of interface separation well, which is worth learning from.