Section separation principle - program for the interface

I read about SOLID and other design principles. I thought the ISP was the same as "Program for an interface, not an implementation." But it looks like these are different principles?

Is there any difference?

+20
oop design-patterns solid-principles isp-principle interface-segregation-principle
Feb 12 2018-12-12T00:
source share
6 answers

ISP focuses on the idea of ​​each interface representing one discrete and cohesive behavior.

That is, each logical group of things that an object should perform will be mapped to one specific interface. A class may want to do a few things, but each thing will be mapped to a specific interface representing this behavior. The idea is that each interface is very focused.

+31
Feb 12 2018-12-12T00:
source share

Robert Martin has a very good explanation of the principle of interface segregation (ISP) in his book UML for Java Programmers. Based on this, I do not think that ISP is an interface that "focuses" on one logical, consistent group of things. Because it goes without saying; or at least that should be taken for granted. Each class, interface, or abstract class must be designed this way.

So what is an ISP? Let me explain this with an example. Say you have class A and class B, which is a client of class A. Suppose class A has ten methods, of which only two are used B. Now, B should know about all ten methods of A? Probably not - the principle of Information is hidden. The more you reveal, the more you create a chance for a connection. For this reason, you can insert an interface called C between two classes (segregation). This interface will only declare two methods that are used by B, and B will depend on this interface, not directly on A.

So now

class A { method1() method2() // more methods method10() } class B { A a = new A() } 

will become

 interface C { method1() method2() } class A implements C{ method1() method2() // more methods method10() } class B { C c = new A() } 

This prevents B from knowing more than necessary.

+38
Feb 13 '12 at 3:01
source share

Suppose you have one bold interface with many methods that you need to implement.

Any class that implements this bold interface should provide an implementation for all of these methods. Some of the methods may not apply to this particular class. But still, it must ensure implementation in the absence of the principle of separation of segregation.

Let's look at an example code in the absence of interface segregation.

 interface Shape{ public int getLength(); public int getWidth(); public int getRadius(); public double getArea(); } class Rectangle implements Shape{ int length; int width; public Rectangle(int length, int width){ this.length = length; this.width = width; } public int getLength(){ return length; } public int getWidth(){ return width; } public int getRadius(){ // Not applicable return 0; } public double getArea(){ return width * length; } } class Square implements Shape{ int length; public Square(int length){ this.length = length; } public int getLength(){ return length; } public int getWidth(){ // Not applicable return 0; } public int getRadius(){ // Not applicable return 0; } public double getArea(){ return length * length; } } class Circle implements Shape{ int radius; public Circle(int radius){ this.radius = radius; } public int getLength(){ // Not applicable return 0; } public int getWidth(){ // Not applicable return 0; } public int getRadius(){ return radius; } public double getArea(){ return 3.14* radius * radius; } } public class InterfaceNoSeggration{ public static void main(String args[]){ Rectangle r = new Rectangle(10,20); Square s = new Square(15); Circle c = new Circle(2); System.out.println("Rectangle area:"+r.getArea()); System.out.println("Square area:"+s.getArea()); System.out.println("Circle area:"+c.getArea()); } } 

exit:

 java InterfaceNoSeggration Rectangle area:200.0 Square area:225.0 Circle area:12.56 

Notes:

  • Shape is a general purpose interface containing the methods needed for all Shape implementations, such as Rectangle , Circle and Square . But only certain methods are needed in the corresponding child elements of the form

      Rectangle : getLength(), getWidth(), getArea() Square : getLength() and getArea() Circle : getRadius() and getArea() 
  • In the absence of segregation, all shapes implemented the entire bold interface: Shape.

We can achieve the same result with the principle of segregation separation if we change the code as follows.

 interface Length{ public int getLength(); } interface Width{ public int getWidth(); } interface Radius{ public int getRadius(); } interface Area { public double getArea(); } class Rectangle implements Length,Width,Area{ int length; int width; public Rectangle(int length, int width){ this.length = length; this.width = width; } public int getLength(){ return length; } public int getWidth(){ return width; } public int getRadius(){ // Not applicable return 0; } public double getArea(){ return width * length; } } class Square implements Length,Area{ int length; public Square(int length){ this.length = length; } public int getLength(){ return length; } public int getWidth(){ // Not applicable return 0; } public int getRadius(){ // Not applicable return 0; } public double getArea(){ return length * length; } } class Circle implements Radius,Area{ int radius; public Circle(int radius){ this.radius = radius; } public int getLength(){ // Not applicable return 0; } public int getWidth(){ // Not applicable return 0; } public int getRadius(){ return radius; } public double getArea(){ return 3.14* radius * radius; } } public class InterfaceSeggration{ public static void main(String args[]){ Rectangle r = new Rectangle(10,20); Square s = new Square(15); Circle c = new Circle(2); System.out.println("Rectangle area:"+r.getArea()); System.out.println("Square area:"+s.getArea()); System.out.println("Circle area:"+c.getArea()); } } 

Notes:

Now, individual shapes, such as Rectangle , Square and Circle , implemented only the necessary interfaces and got rid of unused methods.

+9
Feb 13 '16 at 16:16
source share

Agree with both answers above. To give an example of the smell of TrueWill code above, you should not do this:

 @Override public void foo() { //Not used: just needed to implement interface } 
+1
May 6 '13 at 9:14
source share
  • IWorker Interface:

     public interface IWorker { public void work(); public void eat(); } 
  • Developer Class:

     public class Developer implements IWorker { @Override public void work() { // TODO Auto-generated method stub System.out.println("Developer working"); } @Override public void eat() { // TODO Auto-generated method stub System.out.println("developer eating"); } } 
  • Robot Class:

     public class Robot implements IWorker { @Override public void work() { // TODO Auto-generated method stub System.out.println("robot is working"); } @Override public void eat() { // TODO Auto-generated method stub throw new UnsupportedOperationException("cannot eat"); } } 

For a more complete example, go here .

+1
Jun 20 '17 at 17:58
source share

Here is a real world example of this principle (in PHP)

Problem:

I want various forms of content to have comments / discussions related to them. This content can be anything from a forum topic, from a news article to a user profile to a private conversation-style message.

Architecture

We will need a reusable DiscussionManager class that binds the Discussion to this content object. However, the four examples above (and many others) are conceptually different from each other. If we want the DiscussionManager use them, then all four + should have one common interface that they all share. There is no other way to use them to use the DiscussionManager if you do not want your arguments to be bare (for example, type checking is not).

Solution: A Discussable interface with these methods:

  • attachDiscussion($topic_id)
  • detachDiscussion()
  • getDiscussionID()

Then the DiscussionManager might look like this:

 class DiscussionManager { public function addDiscussionToContent(Discussable $Content) { $Discussion = $this->DiscussionFactory->make( ...some data...); $Discussion->save() // Or $this->DiscussionRepository->save($Discussion); $Content->attachDiscussion($Discussion->getID()); // Maybe saves itself, or you can save through a repository } public function deleteDiscussion(Discussable $Content) { $id = $Content->getDiscussionID(); $Content->detatchDiscussion(); $this->DiscussionRepository->delete($id); } public function closeDiscussion($discussion_id) { ... } } 

Thus, the DiscussionManager does not care about any unrelated behavior of the various types of content that it uses. He ONLY takes care of the behavior he needs, regardless of what these behaviors are associated with. Thus, by providing each type of content that you want to discuss with the Discussable interface, you are using the principle of interface segregation.

This is also a good example of a situation where an abstract base class is not a good idea. The forum topic, user profile, and news article are not even conceptually the same thing, so trying to force them to inherit the behavior associated with the discussion leads to a strange connection with the unrelated parent. Using the specific interface that represents the discussions, you can verify that the objects you want to discuss are compatible with the client code that will manage these discussions.

This example can also be a good candidate for using Traits in PHP, for what it's worth.

0
Mar 18 '14 at 16:43
source share



All Articles