Progrmmers Calculator containing functions like hex to decimal, decimal to binary etc. in addition to basic functions
Scientific Calculator containing functions sin, cos, atan etc in addition to basic functions
We designed a CalculatorDisplay inteface, which caters required functionality of basic, programmer & scientific display. At first glance everything seems okay as CalculatorDisplay is providing the three views for different type of calculators.
Interface contains abstract methods of basicView, programmerView & scientificView.
packageorg.learn.without.isp;
publicinterfaceCalculatorDisplay {
voidbasicView();
voidprogrammerView();
voidscientificView();
}
2.2.) BasicCalculatorClass:
BasicCalculator class implements CalculatorDisplay interface.
BasicCalculator implements basicView method.
BascicCalulator does not provide the feature of programmer & scientific calculator, henec BasicCalculator does not implement programmerView & scientificView methods.
thrownewNotImplementedException("ProgrammerCalculator:scientificView not implemented");
}
}
3. Issues with existing design:
BasicCalculator class is forced to provide an implementation of the programmerView & scientificView interfaces even though the BasicCalculator doesn’t uses it.
ScientificCalculator & ProgrammerCalculator classes are forced to implement the programmerView & scientificView methods respectively.
It doesn’t look greate design, its clear violation of interface segregation design principle.
We should revisit our current design approach of CalculatorDisplay. CalculatorDisplay interface seems to contain many interfaces and which are not cohesive. Robert C Martin calls them the ‘fat’ or ‘polluted’ interfaces. These ‘fat’ interfaces introduce unwanted dependencies in the classes e.g. BasicCalculator, ScientificCalculator classes etc. What is the right way to define the interfaces?
4. Application code after moving non-cohesive interfaces (ISP compliant)
4.1.) Redesigned or Cohesive Interfaces:
Segregation the interfaces so that we will have cohesive interfaces.
packageorg.learn.isp;
publicinterfaceBasicDisplay {
voidbasicView();
};
packageorg.learn.isp;
publicinterfaceScientificDisplay {
voidscientificView();
};
packageorg.learn.isp;
publicinterfaceProgrammerDisplay {
voidprogrammerView();
};
What we have achieved from above segregation?
We have separate interfaces for each type of displays
BasicDisplay, ProgrammerDisplay and ScientificDisplay.
We have split out our Fat interface i.e. CalculatorDisplay to corresponding cohesive interfaces (BasicDisplay, ScientificDisplay & ProgrammerDisplay).
4.2.) BasicCalculator Class:
BasicCalculator Class implements the BasicDisplay interface & our class looks fine now.