➡ SRP (Single Responsibility Principle)
The single responsibility principle states that a class should have responsibility over a single part of the functionality of the application. The class should be cohesive - designed around a set of related functions.
Example
Problem:
The class CardGame has too many responsibilities: showing the UI, game logic, managing the deck of cards. |
Solution:
Each class has a single responsibility, and will contain methods related to eachother. |
Design patterns
- Adapter - responsibility is to adapt a class to a target interface.
- Decorator - divide a class that implements many possible variants of behavior into several smaller classes.
- Facade - responsibility is to be an intermidiary between the subsystem and the client.
- Factory - responsibility is to instantiate a class.
- MVC - Each part of the program (Model, View, Controller) is designed around one part of the program's functionality. Model - system data, View - presentation and interaction with user, Controller - flow of data between view and model.
- State - organize the code related to particular states into separate classes.
➡ OCP (Open Closed Principle)
The open closed principle states that a class should be open for extension, but close for modification. When adding new functionality, minimal changes should occur in existing code. To code for this principle, we should use abstraction and different subclasses.
Example
Problem:
We want to add a new kind of employee: Consultant. In this case, we need to add two new methods to add and remove this type of employee, make a new list, and modify the code of the getNumberOfEmployees() method to account for this new list. This violates the Open Closed Principle.
Solution:
In this case, the class Company only needs one ArrayList with parameter Employee, one method to add and one to remove, and if we want to add any type of employee, it only needs to extend the Employee abstract class and no existing code needs to be changed. Design patterns
➡ LSP (Liskov Substitution Principle)Liskov Substitution Principle states that a superclass object should be replaceable with a subclass without losing any functionality. In other words, when a class implements an interface or extends a parent class, it should only add functionality, never limit. ExampleProblem: The class Duck does add new functionality to the superclass Bird, but the class Ostrich limits it, by throwing an exception. Solution: In this case, the class FlyingBird contains the method fly( ), and Ostrich doesn't limit the functionality of the class Bird. This design respects the LSP. Design patterns
➡ ISP (Interface Segregation Principle)The Interface Segregation Principle states that no code should be forced to depend on methods it does not use. ExampleProblem: We have two kinds of coffee machine: a Basic machine that brews filter coffee and an Espresso machine that brews espresso coffee. We might have something like this: The problem here is that the BasicCoffeeMachine class inherits the brewEspresso( ) method, and the EspressoMachine inherits the brewFilterCoffee( ) method, which are respectively not used. That violates the Interface Segregation principle. We can override these methods to throw an exception if the client tries to use it. This would also violate the Liskov Substitution Principle. Solution: In this design, the methods are moved to different interfaces. If we have a new machine that uses filter coffee, it can implement the FilterCoffeeMachine interface. And if we have a new brew method, we can add a new interface that extends the CoffeeMachine interface. The classes now use all the methods they inherit, which respects the ISP. Design patterns➡ DIP (Dependency Inversion Principle)The Dependency Inversion Principle states that high-level modules should not depend on low-level modules. Both should depend on the abstraction. The abstractions should not depend on details, but the details should depend on abstractions. ExampleProblem: Take this code for example: public class Copy {
This principle violates the Dependency Inversion Principle because the high-level class Copy depends on the low-level classes. This design is not flexible. For example, to add a new way of writing, like printing to a file, we need to alter the code of the Copy class, which violates the OCP, adding a new method to print to a file. Solution: public class Copy { By inserting a level of abstraction we don't need to change the Copy class when we add new implementations of the Reader or Writer implementations. Design patterns
|
Comments
Post a Comment