Unit – 1
Introduction to Design Patterns and Observer Pattern
Design patterns are ready-to-use descriptions that provide solutions to common and recurrent project issues.
They're the result of a lot of trial and error, as well as a lot of experience. They also represent well-considered object-oriented programming best practises (SOLID, DRY, KISS and YAGNI). The patterns created a way for programmers to communicate, and they're now part of every engineer's primer.
Design patterns, in general, are nothing more than walkthroughs for problems that are worth writing down and understanding. It's worth noting that design patterns don't imply a solution's direct implementation, but rather a sketch of a structure with some distinguishing features that should be tailored to our requirements.
Christopher Alexander first proposed the concept of design patterns in 1977. After that, in 1987, Kent Beck and Ward Cunningham gave birth to current computer science patterns. After a few years, the Gang of Four released "Design Patterns: Elements of Reusable Object-Oriented Software" in 1994. Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides' work is always assisting developers in implementing best practices.
Consider the case in which a fellow programmer tries to explain how a SOAP-based flow between widgets and a class works. It's easier and certainly faster to state, "My walkthrough employs the observer pattern."
Goal
Understand the goal and application of each design pattern before selecting and implementing the appropriate pattern.
Key takeaway
Design patterns are ready-to-use descriptions that provide solutions to common and recurrent project issues.
Design patterns, in general, are nothing more than walkthroughs for problems that are worth writing down and understanding.
Design patterns are high-level answers to problems that we as software engineers encounter frequently. It isn't code - I repeat, IT IS NOT CODE. It's akin to an explanation of how to approach these issues and come up with a solution.
Using these patterns is considered best practices since the solution's design has been thoroughly evaluated, resulting in improved readability of the final code. Design patterns are frequently generated for and used by OOP languages, such as Java, in which the majority of the following examples will be written.
Example
We wish to construct only one instance of a class in numerous real-world circumstances. For example, a country can only have one active president at any given time. A Singleton pattern is the name given to this design. Other software examples include a single database connection shared by several objects, as establishing a separate database connection for each item is expensive. Similarly, instead of developing many managers, an application might have a single configuration manager or error manager that handles all problems.
Need of Design pattern
● Allows designers to communicate more effectively.
● By referring to the pattern name, it is possible to solve a problem.
● Improves the readability of code for programmers.
● By leveraging tried and true development paradigms, you can shorten the time it takes to identify a solution.
● Reduce the amount of time coders spend on each task.
● To achieve flexibility, further degrees of indirection are introduced.
● Reduce the time it takes to comprehend the design.
● Avoid alternatives that prevent reusability and hence reduce diversity.
● Improves the documentation and understanding of the design.
● It makes it easier and faster to grasp the fundamentals of object-oriented design.
Key takeaway
Design patterns are high-level answers to problems that we as software engineers encounter frequently.
In general, a pattern refers to a specific layout that makes it easier to complete certain tasks. Patterns are technical terms for gadgets that assist the programme in communicating the information of their design.
In object-oriented language, the phrase design pattern refers to the process of designing objects, classes, and interfaces hierarchy, as well as factoring them into classes with relationships. Once all of these phases have been identified as a pattern, they can be used to a variety of problems.
A design pattern is a reusable solution to a set of problems that arise frequently in software development. A design pattern is not a completed design; rather, it is a template that may be used to solve a problem in a variety of ways.
Gamma, Helm, Jhonson, and Vlissides are known as the Group of Four for their pioneering work on design patterns (GOF). The GoF design pattern is defined as communication between classes and objects that have been tailored to solve a design problem in a particular context.
The Design Patterns are arranged in a catalog format. These Design Patterns help with software engineering by locating objects, specifying object implementations, interfaces, deciding object granularity, and implementing reuse mechanisms, among other things. The design pattern's Intents define what it does. The following are some of the patterns, along with their names and intentions:
● Abstract Factory: It specifies which factory should be instantiated and provides an interface for creating families of objects (related/dependent) without having to specify their concrete classes.
● Adaptor: Id adapts or changes a class's interface into a different one based on the client's expectations, overcoming the problem of incompatible interfaces and allowing the classes to function together.
● Bridge: It separates abstraction from implementation in order to make them self-contained.
● Builder: It separates sophisticated object constructions from their representations so that several representations can be created using the same creation method.
● Chain Of Responsibility: It allows the handling of command objects by passing them to other objects and exploiting the logic included in the object processing. It decouples the sender and receiver by formatting a chain of receiving objects to convey the request until it is handled by an object.
● Command: Client requests, such as lengthy or queue requests, can be parameterized using the command, which encapsulates the action and its parameters. It also aids in the completion of impossible tasks.
● Composite: It represents items in a tree structure, with each object representing the same interface. Clients can handle individual items and their compositions uniformly as a result of this.
● Decorator: At runtime, a decorator adds new functionality to a class. This gives you the freedom to add functionality to your subclasses.
● Facade: It creates a simplified/unified interface of existing subsystem interfaces to make typical activities easier to handle.
● Factory Method: It focuses on the construction of implementation-specific objects. Allows the subclass to choose which class to instantiate.
● Flyweight: It allows a large number of objects to share common attributes in order to conserve space.
● Interpreter: It is a computer programme that implements a certain computer language to solve a specific problem. It interprets sentences in a language by using an interpreter and representing the grammar of the language.
● Iterator: It hides the underlying representations of sequential aggregate objects elements, allowing them to be used sequentially.
● Mediator: It gives a unified interface to a subsystem's set of interfaces. It allows loose coupling, allowing items to explicitly refer to one another while also allowing interaction between objects to be varied separately.
● Momento: It aids the rollback method by allowing things to revert to their previous state without compromising their encapsulation.
● Observer: When an item changes its state, it triggers an event that alerts and automatically updates other objects. This establishes a one-to-many relationship among the objects.
● Prototype: The sort of objects to be constructed is determined by the prototypical instance. By copying this prototype, new objects are created.
● Proxy: It creates the illusion of control over other items by applying placeholder on them.
● Singleton: It restricts a class's instantiation to a single object while also making it globally accessible.
● State: It allows for changes in the object's behaviour in response to changes in its state. i.e. the type of an object can be changed at runtime.
● Visitors: It describes the skeleton of a programme and allows subclasses to define some algorithm stages as well as redefine certain steps without changing the algorithm's structure.
● Strategy: It specifies the family of algorithms and how they are chosen based on the needs of the clients.
According to the Design Patterns - Elements of Reusable Object-Oriented Software reference book, there are 23 design patterns that can be grouped into three categories: creational, structural, and behavioral patterns.
- Creational Patterns
Rather than instantiating objects directly using the new operator, these design patterns give a mechanism to construct things without obscuring the creation logic. This allows the software more freedom in determining which objects are required for a specific use case.
2. Structural Patterns
These design patterns deal with the composition of classes and objects. Inheritance is a concept that is used to create interfaces and define how to combine items to create new functions.
3. Behavioral Patterns
These design patterns are focused on object communication in particular.
Organization of catalog
Key takeaway
In general, a pattern refers to a specific layout that makes it easier to complete certain tasks. Patterns are technical terms for gadgets that assist the programme in communicating the information of their design.
Finding Appropriate Objects
● The difficult aspect is breaking down a system into objects.
● OO-designs frequently result in classes that have no real-world analogues (low- level classes like arrays).
Strict real-world modelling results in a system that reflects today's realities but not necessarily tomorrow's.
● Less-obvious abstractions are identified via design patterns.
Determining Object Granularity
● The size and quantity of objects might vary greatly.
● The facade pattern specifies how subsystems are represented as objects.
● The Flyweight pattern illustrates how to hold a large number of things in place.
Specifying Object Interfaces
● The interface to the object is the collection of all signatures defined by an object's operations.
● A type is a moniker given to a certain interface.
● An object can have a variety of types, and several objects can have the same type.
● If a type's interface contains the interface of its super type, or if a subtype inherits the interface of its super type, it is a subtype of that type.
● Only the interfaces of objects are known. The interface of an object reveals nothing about how it is implemented.
● The operation that is executed when a request is sent to an object is determined by both the request and the receiving object.
● Dynamic binding is the binding of a request to an object and one of its operations at runtime.
● Dynamic binding can substitute objects with identical interfaces for each other at run-time, thanks to polymorphism.
● Design patterns aid in the definition of interfaces by defining essential elements and the types of data that are transferred through them.
● Interactions between interfaces are also defined by design patterns.
Specifying Object Implementations
● The implementation of an object is determined by its class.
● The fundamental aim of an abstract class is to establish a common interface for its subclasses.
● A mixin class is a type of class that provides an optional interface or functionality to other types of classes.
Class versus Interface Inheritance
● The class of an object determines how the thing is implemented.
● The type of an object only corresponds to its interface.
● There are many different types of objects.
● Different classes of objects can have the same type.
● Class and type relationships: class as type (C++) vs. Interface as type (Java).
● Sub-typing + Implementation inheritance make up class inheritance.
● Interface inheritance is limited to sub-typing (Polymorphism).
● As interfaces, pure abstract classes are used.
● The contrast between class and interface inheritances is crucial to many design patterns.
You can choose the right design pattern by thinking about how design patterns help you identify acceptable objects, decide object granularity, specify object interfaces, and a variety of other ways design patterns solve problems.
● Scan intent sections: We may determine the suitable design pattern by looking at the intent part of each design pattern's specification.
● Study how patterns interrelate: The patterns' associations will guide us in selecting the proper pattern or combination of patterns.
The diagram below will assist you in remembering the following patterns:
● Study patterns of like purpose: Each design pattern description will end with a comparison of that pattern to other designs in the same category. This can help you see the similarities and contrasts across patterns with comparable goals.
● Examine a cause of redesign: Examine your issue to see if there are any potential redesign causes. Then have a look at the pattern library to see if there are any patterns that can help you avoid redesigning.
● Consider what should be variable in your design: Consider what you'd like to be able to modify without having to start over. Here, the emphasis is on encapsulating the concept of variation.
In the context of software engineering, a design pattern is a template or reusable solution to typical software design problems. Classes and objects, as well as interfaces, are commonly used to represent this. The "Reusability of Solutions" design pattern is one example of how a design pattern may be used to tackle software development difficulties and enable the construction of highly cohesive modules with coupling.
Design patterns can help developers save time by providing tried-and-true development paradigms. Effective software design necessitates taking into account challenges that may not be apparent until later in the implementation process. For coders and architects familiar with the patterns, reusing design patterns helps to eliminate subtle flaws that can lead to large difficulties and improves code readability.
People frequently only know how to apply specific software design strategies to specific challenges. These methods are challenging to apply to a broader set of issues. Design patterns are generic solutions that are documented in a way that does not necessitate specifics connected to a specific situation.
Patterns also allow engineers to speak about software interactions using well-known, well-understood terms. Common design patterns can be improved over time, making them more robust than ad-hoc designs.
In software development, Design Patterns are used in two ways.
● Common platform for developers
Design patterns define a common language and are tailored to a given context. A singleton design pattern, for example, denotes the use of a single object, thus all developers who are familiar with single design patterns will use single objects, and they will be able to detect whether a programme is following a singleton pattern.
● Best Practices
Design patterns have evolved over time to provide the best answers to specific problems encountered during software development. Learning these patterns makes it easier and faster for inexperienced developers to learn software design.
References:
- Head First Design Patterns, by Eric Freeman and Elisabeth Freeman
- Design Patterns Explained, by Shalloway and Trott
- Introduction to design Patterns in C++ with Qt by Alan Ezust, Paul Ezust