Design Patterns Tutorial For Beginners

Patterns are something that are repetitive in nature. When we write some code, many of them are reused in software engineering. The repeated code can be represented as generic solutions for the common problems encountered during design OOAD and can therefore be considered to be patterns. Design patterns are relevant when there are common problems in code.

Consider a scenario in which we need to deliver a project to the customer and the project is about to be completed or is already completed. Now the customer is always changing their mind and they continue to change the requirements. When we added the new code we encountered the following:

  • It is very hard to change the code because every change affects another part of the system.
  • When we make a change an unexpected part of the system breaks.
  • It is hard to use in other parts of modules or pages or with another application.

So design patterns are useful here. We need to design the code in such a way that, when changes to the requirements happen, the changes to the code should be minimumal. Patterns can be used across multiple domains and used to solve recurring problems, multiple domains means in our daily life when possible.

Key Concepts used for Design Patterns

Abstraction

Focusing upon key or essential characteristics of objects, the object does not hold all of the characteristics. An object is an entity that has a specified number of characteristics.
Abstraction is used for hiding the unwanted data or characteristics and giving only relevant data.

Encapsulation

It hides the internal details of objects. Encapsulation is hiding the code and data into a single unit to protect the data from the outer world.

Abstraction and encapsulation are complimentary to each other. Abstraction is a thought process, it's nothing, but what is necessary. Encapsulation is the actual implementation in which abstraction is implemented.

Polymorphism

Polymorphism means many forms of a subject or an object.

In polymorphism we will declare methods with the same name and different parameters in the same class or methods with the same name and same parameters in different classes. Polymorphism has the ability to provide various implementations of methods that are implemented with the same name.

Polymorphism is of the following two types:

Compile Time Polymorphism (called Early Binding or Overloading or static binding).

Run Time Polymorphism (called Late Binding or Overriding or dynamic binding).

Modularity

Modularity divides a system into cohesive and loosely coupled modules. Modules can be considered to be divided into sub-modules. For example, a typical banking application can have various modules such as funds transfer, accounts, cheque payment and so on.

Each module should be self-contained and most of the modules would work independently and if dependent on other modules. Each module can work together to achieve the objectives of the application or finally get the job done.

Namespace

Namespaces group classes together logically into one logical structure.

Inheritance

Inheritance is the property of getting all the properties and behaviours from the base class to a child class. Inheritance gives us code reuse, it extends and modifies the behaviour defined in the base class.

Association

Association is a relationship where two components are linked to each other. This kind of relation is also referred to as a using relationship, where one class instance uses the other class instance or vice-versa, or both may be using each other.

They don't have no owner, have their own lifetime and child objects are all independent of each other.

Example

Employee–Skill set relationships, Student-Course relationship.

(An employee can have multiple skills and each skill can be owned by multiple employees.)

Aggregation

Aggregation is the same as association but with the additional point that there is an ownership of the instances. The inner object lifetime is not controlled by the outer object. For example, a classroom to student relationship. if the classroom is destroyed, the student will be part of a new classroom and will not be destroyed. Here are some other examples.

Student-Classroom

Engine-Car

Composition

Composition means one object is contained in another object. A
child object does not have their own life cycle, it depends on the parent's life cycle. The parent class is responsible for creating or destroying the child class. The inner object lifetime is controlled by the outer object.

Here are some examples:

Books-Library (If the library is destroyed then the books are also destroyed.)

companyLocation-Company (If the company is closed then the locations are also closed.)

Buttons-Windows (If the window is closed then the buttons are also closed.)

OrderDetails-Order (If the order is cancelled then it makes no sense to look at the order details.)

Diagrams for Association Composition and Aggregation

 
Important Principle of design patterns

These are some of the design patterns principle used to achieve a good architecture of an application.

SRP

Single Responsibility Principle
: No more than one reason to change a class. Design a class to have a single responsibility. Multiple responsibilities for a single class can result in a need for many changes and that leads to instability of that class.

OCP

Open and Closed
Principle: open for extension and closed for modification and design by extensibility.

LSP

Functions that reference a base class must be able to use to the object of the derived class without even knowing them.

DIP

Dependency Inversion Principle. The Dependency Inversion Principle provides the guidelines to write loosely-coupled classes.

High-level modules should not depend on low-level modules. Both should depend on abstractions.

Abstractions should not depend upon details. Details should depend upon abstractions.

Dry (Don't Repeat Yourself): Code should occur exactly once in the system. No repetition and no copy and paste of the code.

KISS (Keep it Simple, Stupid): If we write simple code then the issues that develop from the code will be simple. Unnecessarily complex code should be avoided.

YAGNI (You aren't gonna need it): Implement the things when you need them.

Characteristics of good design and how to achieve it 

These are the characteristics of good design:

  • Maintainable/Readable/Easily understandable
  • Reusable
  • Easier to change if requirement change
  • Perform better
  • Modular/Componentized
  • Scalability: how much load it can handle

    To design a good system, here are some of the key consideration that are used by developers and architects.



  • Various Types of Design Patterns

    There are many design patterns used across the industry. People may find their own patterns when implementing their own code and practice. Few design patterns are used widely in designing enterprise applications (there are many more patterns excluding these but the following patterns are used widely).

    • Gang of Four Patterns (23 GOF patterns)
    • SOA and Messaging Patterns
    • Model-View Patterns Patterns
    • Model-View controller Patterns
    • Model-View ViewModel patterns
    • Domain driven Design patterns

    Those are some of the basic design patterns. I hope now you have a basic understanding of design patterns. Thanks for reading.

    The following are some of the design pattern principles to create a well-architectured application.

    SRP

    Single Responsibility Principle
    : No more than one reason to change a class. Design a class to have a single responsibility. Multiple responsibilities for a single class can result in a need for many changes and that leads to instability of that class.

    OCP

    Open and Close
    Principle: Open for extension and closed for modification and design by extensibility.

    LSP

    Functions that reference a base class must be able to use to an object of the derived class without even knowing them.

    DIP

    Dependency Inversion Principle. The Dependency Inversion Principle provides the guidelines for writing loosely-coupled classes.

    High-level modules should not depend on low-level modules. Both should depend on abstractions.

    Abstractions should not depend upon details. Details should depend upon abstractions.

    Dry (Don't Repeat Yourself): Code should occur exactly once in the system. No repetition and no copy and paste of code.

    KISS (Keep it Simple, Stupid): If we write simple code then the issues that develop from the code will be simple. Unnecessarily complex code should be avoided.

    YAGNI (You aren't gonna need it): Implement the things when you need them.

    Characteristics of good design and how to achieve it 

    These are the characteristics of good design:

  • Maintainable/Readable/Easily understandable
  • Reusable
  • Easier to change if requirement change.
  • Perform better
  • Modular/Componentized
  • Scalability: how much load it can handle.

    To design a good system, here are some of the key considerations used by developers and architects.



  • Various Types of Design Patterns

    There are many design patterns used across the industry. People may find their own patterns when implementing their own code and practice. A few design patterns are used widely in designing enterprise applications (there are many more patterns excluding these but the following patterns are used widely).

    • Gang of Four Patterns (23 GOF patterns)
    • SOA and Messaging Patterns
    • Model-View Patterns Patterns
    • Model view controller Patterns
    • Model View viewModel patterns
    • Domain driven Design patterns

    These are some of the basic design patterns. I hope now you have some basic knowledge of design patterns. Thanks for reading.