The document provides an overview of the GoF design patterns including the types (creational, structural, behavioral), examples of common patterns like factory, abstract factory, singleton, adapter, facade, iterator, observer, and strategy, and UML diagrams illustrating how the patterns can be implemented. Key aspects of each pattern like intent, relationships, pros and cons are discussed at a high level. The document is intended to introduce software engineers to design patterns and how they can be applied.
4. Introduction
Each pattern describes a problem which occurs over and over
again in software programming environment and then describes
the core of solution to that problem.
5. Introduction
Recipes for the common OO problems.
Code reuse
Open for extension but not for modification
Encapsulate what varies
Single responsibility principle
Program against interface but not against implementation
Avoid Tight coupling
6. OOD principles
OOD principles to design a class:
SRP: The single responsibility principle
A class should have only one and only one reason to change.
OCP – The open closed principle
Should be able to extend the behavior but not modify the existing behavior.
LSP – The Liskov Substitution principle
Derived classes must be substantial to their base classes.
DIP – The dependency inversion principle
Depend on abstractions, not on concretions.
ISP – The interface Segregation principle
Make fine grained interfaces that are specific to client.
7. Uses of Design Patterns
Finding appropriate objects.
Determining object granularity.
Specifying object interfaces.
Specifying object implementations.
Programming to an interface not to an implementation.
8. Question
What is difference or use of below code snippets:
Interface ICreditCard{…}
Class HDFCCreditCard : ICreditCard {….}
ICreditCard _cc = new HDFCCreditCard();
HDFCCreditCard cc = new HDFCCreditCard();
9. When to go for Interfaces
APIs
Tightly coupled code
Future proofing
Code clarity
12. Association Vs. Aggregation Vs. Composition
Association is a relationship between two classes.
Aggregation is the relationship between two classes.
Composition is the special type of Aggregation/Association. Association
Aggregation
Composition
14. Scope of Pattern
Object level Class level
• Deal with object • Deal with relationships
relations. between classes and
• Relationships are their subclasses.
dynamic. • Relationships are static.
15. Types of Design Patterns
• Which can be used while creating objects.
Creational • Factory, Abstract Factory, Singleton,
Prototype, Builder
• Which can be used to combine objects and
Structural classes in order to build structured objects.
• Adapter, Façade, Proxy, Composite, etc.
• Which can be used to build a computation
Behavioral and to control data flows.
• Iterator, Observer, Strategy, State, etc.
17. Factory
Defines an interface for creating objects but let sub-classes decide
which of those instantiate.
Enables the creator to defer Product creation to a sub-class.
20. Factory Pros & Cons.
Pros:
Shields clients from concrete classes.
If a framework follows a Factory pattern, it enables the third party
developers to plug-in new products.
Cons:
Coding a new product means, writing two classes one for concrete
factory and concrete product.
Inheritance based.
21. ABSTRACT FACTORY
Create instances of classes belonging to different families.
Factory method often used in abstract factory pattern to implement
the create methods.
23. Abstract Factory Facts
Use when a system should be independent of how its products are
created, composed and represented.
When a system should be configured with one of multiple families of
products.
When a family of objects is designed to be worked together, and
you need to enforce this constraint.
If you want to provide a class library of products, and you want to
reveal just their interfaces but not implementations.
24. Example
Check Cash
Deposit Deposit
Book
Payment
order
Payment
25. Pros./cons.
Pros:
Shields clients from concrete classes.
Easy to switch product family at run-time, just change concrete
factory.
Cons:
Adding a new product means changing factory interface and all
concrete factories.
26. Factory Vs. Abstract Factory
Factory :
Use the Factory Method pattern when there is a need to decouple a
client from a particular product that it uses.
Use the Factory Method to relieve a client of responsibility for creating
and configuring instances of a product.
Abstract Factory:
Use the Abstract Factory pattern when clients must be decoupled from
product classes.
Especially useful for program configuration and modification The
Abstract Factory pattern can also enforce constraints about which
classes must be used with others. It may be a lot of work to make new
concrete factories.
27. Singleton
A class with only one single possible instance.
Private constructor
Global access
30. More about Singleton
Thread-safe implementation for multi-threading use.
Lazy instantiation
Early instantiation
31. Object Pool Pattern
Caching the instances that are costly to create every time.
Also called Object Cache or Resource Cache design pattern.
It is advised to keep all reusable expensive objects that are not
currently in use in the container so that they can be managed by
one rational policy. To achieve this, the reusable Pool class is
designed to be a singleton class.
35. Structural Patterns
Adapter
• Translates one interface for a class into a compatible
interface.
Proxy
• Provides a class which limits the access to the original
class.
Facade
• A facade is an object that provides a simplified interface
to a larger body of code, such as a class library.
36. Adapter Pattern
Translates one interface for a class into a compatible interface.
An adapter allows classes to work together that normally could not
because of incompatible interfaces, by providing its interface to
clients while using the original interface.
39. Proxy pattern
Provides a class which limits the access to the original class.
It might be for
Security reasons
To reduce memory foot print
To avoid complex object usage
42. Proxy Facts
Introduces a level of indirection when accessing an object.
Can hide the fact that the object resides in different address space.
Can perform optimizations such as creating an object on demand.
43. Facade Pattern
A facade is an object that provides a simplified interface to a larger
body of code, such as a class library.
Make a software library easier to use, understand and test, since the
facade has convenient methods for common tasks.
Make the library more readable.
Reduce dependencies of outside code on the inner workings of a
library, since most code uses the facade, thus allowing more
flexibility in developing the system.
Wraps a poorly designed collection of APIs with a single well-
designed API.
47. Behavioral Patterns
Iterator
•An iterator is used to traverse through the container and access the
container’s elements.
Observer
•The observer pattern is a software design pattern in which an object, called
the subject, maintains a list of its dependents, called observers, and notifies
them automatically of any state changes, usually by calling one of their
methods.
Strategy
•The strategy pattern (also known as the policy pattern) is a particular software
design pattern, whereby algorithms can be selected at runtime.
48. Iterator pattern
An iterator is used to traverse through the container and access the
container’s elements.
The essence of the Iterator Factory method Pattern is to "Provide a
way to access the elements of an aggregate object sequentially
without exposing its underlying representation."
50. More about Iterator
Robust iterators
Who defines the traversal algorithms?
51. Observer Pattern
Motivation
Intent
Definition - The observer pattern is a software design pattern in
which an object, called the subject, maintains a list of its
dependents, called observers, and notifies them automatically of
any state changes, usually by calling one of their methods.
53. More about Observer pattern..
Many Subjects to Many Observers
Who triggers the update
Making sure Subject state is self-consistent before notification
58. More about Strategy..
Passing Data to and from Strategy object.
The strategy design pattern splits the behaviour (there are many
behaviours) of a class from the class itself.
This has some advantages, but the main draw back is that a client
must understand how the Strategies differ.
Since clients get exposed to implementation issues the strategy
design pattern should be used only when the variation in behaviour
is relevant to them.
60. Thanks
Thanks for listening, if you have any questions mail me at
sv250048@ncr.com.
MSN Id: sv250048@ncr.com
Feedback: https://www.recognition4me.com/recognition4me
Notes de l'éditeur
APIsI believe you get the most advantage from using interfaces as often as possible when you are writing an API. In an API, you want your code to be as loosely coupled as possible in terms of input and output; after all, you have no control over what the consuming application will need.There may be a time when it is tempting to work with a List<T> within a piece of code, and then just return the List<T>, for example. The consumers of the API usually do not need all of the functionality of List<T>, and you can output IEnumerable<T> instead. This way, if the consumer wants a List<T>, they can have it, or they can have an array of T, or whatever else they might need. By using the common denominator interfaces in your API, you free the consumers from being forced to use or convert to/from your class of choice.Tightly coupled codeIn the fantasy land of Computer Science courses and the blogosphere, developers never write tightly coupled code. In reality, tightly coupled code is a fact of life for the average developer.You aren’t going to make an abstract class and implement the Factory pattern to “future proof” yourself against changes when writing a three line of code class will give you a strong type to shuffle data around. Likewise, coding to interfaces is impractical in many situations; a key sign of this is when you find yourself writing classes that look a lot like structures.If the only or the best way to get something done is to tightly couple code, then trying to abstract some kind of common functionality into an interface is either doomed to fail or merely more effort than it is worth.Future proofingWorking with interfaces can give you a measure of future proofing when you are on the consuming end of things. If you are using a library that outputs interface instances instead of classes, not recasting those instances as classes can protect you from changes down the road. Along the same lines, if you only need a certain subset of functionality contained within an interface, working against that interface is better than working against the class.Go back six or seven years before we had generic types — if you had coded everything to take arrays or Hashtables instead of IEnumerable or ICollection, then if the library ever changed to use List<T> or Dictionary<T>, you would have a long road ahead of you to convert over.Code clarityCoding with interfaces can improve code readability. How? Because there are fewer “moving parts” for the reader to keep in mind. When you work with an interface, it is more clear what your intentions are and what the capabilities will be. Code is more self-documenting when working with interfaces for this reason.Sometimes an interface just won’t doSome folks take the use of interfaces to an unworkable extreme. Avoid this at all costs. There will be times when you simply cannot boil down the essence of a variable or a method parameter (or whatever) to an interface. In fact, this is more likely than not. Don’t try to force the issue; it’s better to just use a class and move on with your life than to try to make things work with an interface.
Encapsulation: The encapsulation is the inclusion within a program object of all the resources need for the object to function - basically, the methods and the data. In OOP the encapsulation is mainly achieved by creating classes, the classes expose public methods and properties. Association: Association is a (*a*) relationship between two classes. It allows one object instance to cause another to perform an action on its behalf. Association is the more general term that define the relationship between two classes, where as the aggregation and composition are relatively special.Aggregation: Aggregation is the (*the*) relationship between two classes. When object of one class has an (*has*) object of another, if second is a part of first (containment relationship) then we called that there is an aggregation between two classes. Unlike association, aggregation always insists a direction.Composition: Special type of Aggregation means if the second object disposed the first object automatically will be disposed.
In this case I can say that University aggregate Chancellor or University has an (*has-a*) Chancellor. But even without a Chancellor a University can exists. But the Faculties cannot exist without the University, the life time of a Faculty (or Faculties) attached with the life time of the University . If University is disposed the Faculties will not exist. In that case we called that University is composed of Faculties. So that composition can be recognized as a special type of an aggregation.
Sometimes it's important to have only one instance for a class. For example, in a system there should be only one window manager (or only a file system or only a print spooler).It involves only one class which is responsible to instantiate itself, to make sure it creates not more than one instance; in the same time it provides a global point of access to that instance. In this case the same instance can be used from everywhere, being impossible to invoke directly the constructor each time.
Example 1 - Logger ClassesThe Singleton pattern is used in the design of logger classes. This classes are ussualy implemented as a singletons, and provides a global logging access point in all the application components without being necessary to create an object each time a logging operations is performed.Example 2 - Configuration ClassesThe Singleton pattern is used to design the classes which provides the configuration settings for an application. By implementing configuration classes as Singleton not only that we provide a global access point, but we also keep the instance we use as a cache object. When the class is instantiated( or when a value is read ) the singleton will keep the values in its internal structure. If the values are read from the database or from files this avoids the reloading the values each time the configuration parameters are used. Example 3 - Accessing resources in shared modeIt can be used in the design of an application that needs to work with the serial port. Let's say that there are many classes in the application, working in an multi-threading environment, which needs to operate actions on the serial port. In this case a singleton with synchronized methods could be used to be used to manage all the operations on the serial port.Example 4 - Factories implemented as SingletonsLet's assume that we design an application with a factory to generate new objects(Acount, Customer, Site, Address objects) with their ids, in an multithreading environment. If the factory is instantiated twice in 2 different threads then is possible to have 2 overlapping ids for 2 different objects. If we implement the Factory as a singleton we avoid this problem. Combining Abstract Factory or Factory Method and Singleton design patterns is a common practice.
Reusable - Wraps the limited resource, will be shared by several clients for a limited amount of time.Client - uses an instance of type Reusable.ReusablePool - manage the reusable objects for use by Clients, creating and managing a pool of objects.When a client asks for a Reusable object, the pool performs the following actions:- Search for an available Reusable object and if it was found it will be returned to the client.- If no Reusable object was found then it tries to create a new one. If this actions succeds the new Reusable object will be returned to the client.- If the pool was unable to create a new Reusable, the pool will wait until a reusable object will be released.
One of the most common data structures in software development is what is generic called a collection. A collection is just a grouping of some objects. They can have the same type or they can be all cast to a base type like object. A collection can be a list, an array, a tree and the examples can continue. But what is more important is that a collection should provide a way to access its elements without exposing its internal structure. We should have a mechanism to traverse in the same way a list or an array. It doesn't matter how they are internally represented. The idea of the iterator pattern is to take the responsibility of accessing and passing trough the objects of the collection and put it in the iterator object. The iterator object will maintain the state of the iteration, keeping track of the current item and having a way of identifying what elements are next to be iterated.The abstraction provided by the iterator pattern allows you to modify the collection implementation without making any changes outside of collection. It enables you to create a general purpose GUI component that will be able to iterate through any collection of the application.
Robust Iterators- Can the aggregate be modified while a traversal is ongoing? An iterator that allows insertion and deletions without affecting the traversal and without making a copy of the aggregate is called a robust iterator. A robust iterator will make sure that when elements are added or removed from an aggregate during iteration; elements are not accessed twice or ignored. Lets' say we don't need a robust iterator. If the aggregate can not be modified (because the iteration is started), it should be made explicitly, meaning that the client should be aware of it. We can just return a false value what an element is added to the collection stating that the operation has failed, or we can throw an exception. An alternative solution is to add functions to change the aggregate in the iterator itself. For example we can add the following methods to our iterator:bool remove();bool insertAfer();bool insertBefore();In the case when this solution is chosen the iterator handles the changes of the aggregator. In this case the operation to change the iteration should be added to the iterator interface or base class not to the implementation only, in order to have a general mechanism for the entire application.Who defines the traversal algorithm?The algorithm for traversing the aggregate can be implemented in the iterator or in the aggregate itself. When the traversal algorithm is defined in the aggregate, the iterator is used only to store the state of the iterator. This kind of iterator is called a cursor because it points to the current position in the aggregate. The other option is to implement the traversal algorithm in the iterator. This option offers certain advantages and some disadvantages. For example it is easier to implement different algorithms to reuse the same iterators on different aggregates and to subclass the iterator in order to change its behavior. The main disadvantage is that the iterator will have to access internal members of the aggregate. In Java and .NET this can be done, without violating the encapsulation principle, by making the iterator an inner class of the aggregate class.
We can not talk about Object Oriented Programming without considering the state of the objects. After all object oriented programming is about objects and their interaction. The cases when certain objects need to be informed about the changes occurred in other objects are frequent. To have a good design means to decouple as much as possible and to reduce the dependencies. The Observer Design Pattern can be used whenever a subject has to be observed by one or more observers.Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.The observer pattern is used when: The change of a state in one object must be reflected in another object without keeping the objects tight coupled. The framework we are writing needs to be enhanced in future with new observers with minimal changes.Some Classical Examples:Model View Controller Pattern - The observer pattern is used in the model view controller (MVC) architectural pattern. In MVC the this pattern is used to decouple the model from the view. View represents the Observer and the model is theObservable object.Event management - This is one of the domains where the Observer patterns is extensively used. Swing and .Net are extensively using the Observer pattern for implementing the events mechanism.
The strategy pattern (also known as the policy pattern) is a particular software design pattern, whereby algorithms can be selected at runtime. Define a family of algorithms, encapsulate each one, and make them interchangeable.Strategy lets the algorithm vary independently from clients that use it.In the classic implementation of the pattern the client should be aware of the strategy concrete classes. In order to decouple the client class from strategy classes is possible to use a factory class inside the context object to create the strategy object to be used. By doing so the client has only to send a parameter (like a string) to the context asking to use a specific algorithm, being totally decoupled of strategy classes.
Usually each strategy need data from the context have to return some processed data to the context. This can be achieved in 2 ways. creating some additional classes to encapsulate the specific data.passing the context object itself to the strategy objects. The strategy object can set returning data directly in the context.When data should be passed the drawbacks of each method should be analysed. For example, if some classes are created to encapsulate additional data, a special care should be paid to what fields are included in the classes. Maybe in the current implementation all required fields are added, but maybe in the future some new strategy concrete classes require data from context which are not include in additional classes. Another fact should be specified at this point: it's very likely that some of the strategy concrete classes will not use field passed to the in the additional classes.On the other side, if the context object is passed to the strategy then we have a tighter coupling between strategy and context.