Posts

Showing posts from March, 2022

The factory pattern

Image
  The factory pattern As discussed in the previous chapter, inheritance is one of the fundamental concepts in object-oriented programming. Along with subtyping polymorphism, it gives us the is/a relationship. A  Car  object can be handled as a  Vehicle  object. A  Truck  object can be handled as a  Vehicle  object too. On one hand, this kind of abstraction makes our code thinner, because the same piece of code can handle operations for both  Car  and  Truck  objects. On the other hand, it gives us the option to extend our code to new types of  Vehicle  objects by simply adding new classes such as  Bike  and  Van without modifying it. When we deal with such scenarios, one of the trickiest parts is the creation of objects. In object-oriented programming, each object is instantiated using the constructor of the specific class, as shown in the following code: Vehicle vehicle = new Car(); This piece of ...

Singleton pattern

Image
  Singleton pattern The singleton pattern is probably the most widely used design pattern since the inception of Java. It is a simple pattern, easy to understand and to use. Sometimes it is used in excess, and in scenarios where it is not required. In such cases, the disadvantages of using it outweigh the advantages it brings. For this reason, the singleton is sometimes considered an anti-pattern. However, there are many scenarios where singletons are necessary. As its name suggests,  the singleton pattern is used to ensure that only a single instance of an object can be created. In addition to that, it also provides global access to that instance.  The implementation of a singleton pattern is described in the following class diagram: The implementation of the singleton pattern is very simple and consists of a single class. To ensure that the singleton instance is unique, all singleton constructors should be made private. Global access is done through a static method that...

Creational Patterns

  Creational Patterns  Creational patterns are patterns that deal with object creation Singleton pattern Simple factory pattern Factory method patterns Abstract factory pattern Builder pattern Prototype pattern Object pool pattern

Dependency inversion principle

Image
  Dependency inversion principle "High-level modules should not depend on low-level modules. Both should depend on abstractions." "Abstractions should not depend on details. Details should depend on abstractions." In order to understand this principle, we must explain the important concept of coupling and decoupling. Coupling refers to the degree to which modules of a software system are dependent on one another. The lower the dependency is, the easier it is to maintain and extend the system. There are different approaches to decoupling the components of a system. One of them is to separate the high-level logic from the low-level modules, as shown in the following diagram. When doing this, we should try to reduce the dependency between the two by making them depend on abstractions. This way, any of them can be replaced or extended without affecting other modules:

Interface Segregation Principle

Image
  Interface Segregation Principle "Clients should not be forced to depend upon interfaces that they don't use."   When applied, the   Interface Segregation Principle   ( ISP ) reduces the code coupling, making the software more robust, and easier to maintain and extend. ISP was first announced by Robert Martin, when he realized that if the principle is broken and clients are forced to depend on interfaces they don't use, the code becomes so tightly coupled that it's almost impossible to add new functionality to it. In order to better understand this, let's again take the car-service example (refer to the following diagram). Now we need to implement a class named  Mechanic . The mechanic repairs cars, so we add a method of repair car. In this case, the  Mechanic  class depends upon the  I  class. However, the  Car  class exposes a richer sets of methods than the  Mechanic  class needs: This is a bad design because if w...

Liskov Substitution Principle

Image
  Liskov Substitution Principle Barbara Liskov states that,  Derived types must be completely substitutable for their base types . The  Liskov Substitution Principle  ( LSP ) is strongly related to subtyping polymorphism. Based on subtyping polymorphism in an object-oriented language,  a derived object can be substituted with its parent type.  For example, if we have a  Car  object, it can be used in the code as a  Vehicle . The LSP states that, when designing the modules and classes, we must make sure that the derived types are substitutable from a behavior point of view. When the derived type is substituted with its supertype, the rest of the code will operate with it as it is the subtype. From this point of view, the derived type should behave as its supertype and should not break its behavior. This is called strong behavioral subtyping. In order to understand the LSP, let's take an example in which the principle is violated. While we are ...