Design Patterns PDF
Design Patterns PDF
#design-
patterns
Table of Contents
About 1
Remarks 2
Examples 2
Introduction 2
Chapter 2: Adapter 4
Examples 4
Adapter (Java) 4
Java Example 5
Chapter 3: blackboard 11
Examples 11
C# Sample 11
Examples 15
Remarks 18
Examples 18
Java / Lombok 24
Examples 28
Examples 30
Command pattern example in Java 30
Examples 33
Composite logger 33
Introduction 35
Remarks 35
Examples 35
Examples 37
Introduction 40
Parameters 40
Examples 40
VendingMachineDecorator 40
Caching Decorator 44
Introduction 46
Remarks 46
Examples 47
Examples 49
Remarks 53
Examples 53
Simple factory (Java) 53
An Abstract Factory 58
Factory method 64
Examples 65
Introduction 67
Examples 67
Examples 69
Remarks 72
Examples 72
Monostate-based hierarchies 73
Remarks 75
Examples 75
Remarks 78
Examples 78
Remarks 83
Examples 83
Remarks 86
Examples 86
Observer / Java 86
Introduction 90
Remarks 90
Examples 90
Introduction 92
Remarks 92
Examples 92
Examples 95
Publish-Subscribe in Java 95
Remarks 97
Examples 97
Remarks 101
Examples 101
Introduction 109
Examples 109
Examples 114
Examples 117
Examples 125
Examples 128
Credits 136
About
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: design-patterns
It is an unofficial and free Design patterns ebook created for educational purposes. All the content
is extracted from Stack Overflow Documentation, which is written by many hardworking individuals
at Stack Overflow. It is neither affiliated with Stack Overflow nor official Design patterns.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to info@zzzprojects.com
https://riptutorial.com/ 1
Chapter 1: Getting started with Design
patterns
Remarks
This section provides an overview of what design-patterns is, and why a developer might want to
use it. Examples may provide a graphical representation of the pattern, a scenario consisting of a
problem given a context in which a pattern can be used and mention possible trade offs.
It should also mention any large subjects within design-patterns, and link out to the related topics.
Since the Documentation for design-patterns is new, you may need to create initial versions of
those related topics.
Examples
Introduction
According to Wikipedia:
(Retrieved: 2016-10-13)
There are many recognized software design patterns, and new ones are proposed on a regular
basis. Other topics cover many of the most common patterns, and the Wikipedia article provides a
more extensive list.
Similarly, there are different ways to classify design patterns, but the original classification is:
The idea of design patterns has been extended to domain-specific design patterns for domains
such as user interface design, data visualization, secure design, web design and business model
design.
Finally, there is a related concept called a software architecture pattern which is described as
being the analogue for design patterns applied to software architectures.
https://riptutorial.com/ 2
Read Getting started with Design patterns online: https://riptutorial.com/design-
patterns/topic/1012/getting-started-with-design-patterns
https://riptutorial.com/ 3
Chapter 2: Adapter
Examples
Adapter Pattern (PHP)
A real world example using a scientific experiment where certain routines are performed on
different types of tissue. The class contains two functions by default to get the tissue or routine
separately. In a later version we have then adapted it using a new class to add a function that gets
both. This means we have not edited the original code and therefore do not run any risk of
breaking our existing class (and no retesting).
class Experiment {
private $routine;
private $tissue;
function __construct($routine_in, $tissue_in) {
$this->routine = $routine_in;
$this->tissue = $tissue_in;
}
function getRoutine() {
return $this->routine;
}
function getTissue() {
return $this->tissue;
}
}
class ExperimentAdapter {
private $experiment;
function __construct(Experiment $experiment_in) {
$this->experiment = $experiment_in;
}
function getRoutineAndTissue() {
return $this->experiment->getTissue().' ('. $this->experiment->getRoutine().')';
}
}
Adapter (Java)
Lets assume that in your current codebase, there exists MyLogger interface like so:
interface MyLogger {
void logMessage(String message);
void logException(Throwable exception);
}
Lets say that you've created a few concrete implementations of these, such as MyFileLogger and
MyConsoleLogger.
You have decided that you want to use a framework for controlling your application's Bluetooth
connectivity. This framework contains a BluetoothManager with the following constructor:
https://riptutorial.com/ 4
class BluetoothManager {
private FrameworkLogger logger;
The BluetoothManager also accepts a logger, which is great! However it expects a logger of which
the interface was defined by the framework and they have used method overloading instead of
naming their functions differently:
interface FrameworkLogger {
void log(String message);
void log(Throwable exception);
}
You already have a bunch of MyLogger implementations that you would like to reuse, but they do
not fit the interface of the FrameworkLogger. This is where the adapter design-pattern comes in:
@Override
public void log(String message) {
this.logger.logMessage(message);
}
@Override
public void log(Throwable exception) {
this.logger.logException(exception);
}
}
By defining an adapter class that implements the FrameworkLogger interface and accepts a MyLogger
implementation the functionality can be mapped between the different interfaces. Now it is
possible to use the BluetoothManager with all of the MyLogger implementations like so:
Java Example
A great existing example of the Adapter pattern can be found in the SWT MouseListener and
MouseAdapter classes.
https://riptutorial.com/ 5
The MouseListener interface looks as follows:
Now imagine a scenario where you are building a UI and adding these listeners, but most of the
time you don't care about anything other than when something is single clicked (mouseUp). You
wouldn't want to constantly be creating empty implementations:
obj.addMouseListener(new MouseListener() {
@Override
public void mouseDoubleClick(MouseEvent e) {
}
@Override
public void mouseDown(MouseEvent e) {
}
@Override
public void mouseUp(MouseEvent e) {
// Do the things
}
});
By providing empty, default implementations, we are free to override only those methods which we
care about from the adapter. Following from the above example:
obj.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent e) {
// Do the things
}
});
To make the use of the adapter pattern and the kind of situation when it may be applied more
imaginable, a small, simple and very concrete example is given here. There will be no code in
here, just UML and a description of the example situation and its problem. Admittedly, the UML
https://riptutorial.com/ 6
content is written like Java. (Well, the hint text said "Good examples are mostly code", I think
design patterns are abstract enough to be introduced in a different way, too.)
In general, the adapter pattern is an adequate solution for a situation when you have incompatible
interfaces and none of them can be directly rewritten.
Imagine you're running a nice little pizza delivery service. Customers can order online on your
website and you have small system using a class Pizza to represent your pizzas and calculate
bills, tax reports and more. The price of your pizzas is given as a single integer representing the
price in cent (of the currency of your choice).
Your delivery service is working out great, but at some point you cannot handle the growing
number of customers on your own anymore but you still want to expand. You decide to add your
pizzas to the menu of a big online meta delivery service. They offer a lot of different meals — not
only pizzas — so their system makes more use of abstraction and has an Interface IMeal
representing meals coming along with a class MoneyAmount representing money.
MoneyAmount consists of two integers as input, one for the amount (or some random currency)
before the comma, and one for the cent amount from 0 to 99 after the comma;
https://riptutorial.com/ 7
Due to the fact that the price of your Pizza is a single integer representing the total price as an
amount of cent (> 99), it is not compatible with IMeal. This is the point where the adapter pattern
comes into play: In case it would take too much effort to change your own system or create a new
one and you have to implement an incompatible interface, you may want to apply the adapter
patttern.
There are two ways of applying the pattern: class adapter and object adapter.
Both have in common that an adapter (PizzaAdapter) works as some kind of translator between the
new interface and the adaptee (Pizza in this example). The adapter implements the new interface (
IMeal) and then either inherits from Pizza and converts its own price from one integer to two (class
adapter)
https://riptutorial.com/ 8
or has an object of type Pizza as an attribute and converts the values of that (object adapter).
https://riptutorial.com/ 9
By applying the adapter pattern, you will kind of "translate" between incompatible interfaces.
https://riptutorial.com/ 10
Chapter 3: blackboard
Examples
C# Sample
Blackboard.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace Blackboard
{
public class BlackBoard
{
public List<KnowledgeWorker> knowledgeWorkers;
protected Dictionary<string, ControlData> data;
public Control control;
public BlackBoard()
{
this.knowledgeWorkers = new List<KnowledgeWorker>();
this.control = new Control(this);
this.data = new Dictionary<string, ControlData>();
}
https://riptutorial.com/ 11
this.data[key] = data;
}
else
{
this.data.Add(key, data);
}
}
}
}
Control.cs
using System;
using System.Collections.Generic;
namespace Blackboard
{
public class Control
{
BlackBoard blackBoard = null;
/// <summary>
/// Selects the next source of knowledge (knowledgeworker by inspecting the
blackgoard)
/// </summary>
void nextSource()
https://riptutorial.com/ 12
{
// observers the blackboard
foreach (KeyValuePair<string, ControlData> value in this.blackBoard.inspect())
{
if (value.Value.problem == "PrimeNumbers")
{
foreach (KnowledgeWorker worker in this.blackBoard.knowledgeWorkers)
{
if (worker.getName() == "PrimeFinder")
{
Console.WriteLine("Knowledge Worker Found");
worker.executeCondition();
worker.executeAction();
worker.updateBlackboard();
}
}
}
}
}
}
}
ControlData.cs
using System;
using System.Collections.Generic;
namespace Blackboard
{
public class ControlData:ICloneable
{
public string problem;
public object[] input;
public object[] output;
public string updateby;
public DateTime updated;
public ControlData()
{
this.problem = null;
this.input = this.output = null;
}
https://riptutorial.com/ 13
ControlData clone;
clone = new ControlData(this.problem, this.input);
clone.updated = this.updated;
clone.updateby = this.updateby;
clone.output = this.output;
return clone;
}
}
}
KnowledgeWorker.cs
namespace Blackboard {
/// <summary>
/// each knowledgeworker is resposible for knowing the conditions under which it can
contribute to a solution.
/// </summary>
abstract public class KnowledgeWorker
{
protected Boolean canContribute;
protected string Name;
public BlackBoard blackboard = null;
protected List<KeyValuePair<string, ControlData>> keys;
public KnowledgeWorker(BlackBoard blackboard, String Name)
{
this.blackboard = blackboard;
this.Name = Name;
}
} }
https://riptutorial.com/ 14
Chapter 4: Bridge Pattern
Examples
Bridge pattern implementation in java
Bridge pattern decouples abstraction from implementation so that both can vary independently. It
has been achieved with composition rather than inheritance.
The crux of Bridge pattern : Two orthogonal class hierarchies using composition (and no
inheritance). The Abstraction hierarchy and Implementation hierarchy can vary independently.
Implementation never refers Abstraction. Abstraction contains Implementation interface as a
member (through composition). This composition reduces one more level of inheritance hierarchy.
Enable different vehicles to have both versions of manual and auto gear system.
Example code:
/* Implementor interface*/
interface Gear{
void handleGear();
https://riptutorial.com/ 15
}
/* Concrete Implementor - 1 */
class ManualGear implements Gear{
public void handleGear(){
System.out.println("Manual gear");
}
}
/* Concrete Implementor - 2 */
class AutoGear implements Gear{
public void handleGear(){
System.out.println("Auto gear");
}
}
/* Abstraction (abstract class) */
abstract class Vehicle {
Gear gear;
public Vehicle(Gear gear){
this.gear = gear;
}
abstract void addGear();
}
/* RefinedAbstraction - 1*/
class Car extends Vehicle{
public Car(Gear gear){
super(gear);
// initialize various other Car components to make the car
}
public void addGear(){
System.out.print("Car handles ");
gear.handleGear();
}
}
/* RefinedAbstraction - 2 */
class Truck extends Vehicle{
public Truck(Gear gear){
super(gear);
// initialize various other Truck components to make the car
}
public void addGear(){
System.out.print("Truck handles " );
gear.handleGear();
}
}
/* Client program */
public class BridgeDemo {
public static void main(String args[]){
Gear gear = new ManualGear();
Vehicle vehicle = new Car(gear);
vehicle.addGear();
https://riptutorial.com/ 16
vehicle.addGear();
}
}
output:
Explanation:
1. Vehicle is an abstraction.
2. Car and Truck are two concrete implementations of Vehicle.
3. Vehicle defines an abstract method : addGear().
4. Gear is implementor interface
5. ManualGear and AutoGear are two implementations of Gear
6. Vehicle contains implementor interface rather than implementing the interface. Compositon of
implementor interface is crux of this pattern : It allows abstraction and implementation to vary
independently.
7. Car and Truck define implementation ( redefined abstraction) for abstraction : addGear() : It
contains Gear - Either Manual or Auto
1. Abstraction and Implementation can change independent each other and they are not
bound at compile time
2. Map orthogonal hierarchies - One for Abstraction and one for Implementation.
https://riptutorial.com/ 17
Chapter 5: Builder Pattern
Remarks
Separates the construction of a complex object from its representation so that the same
construction process can create different representations.
Examples
Builder Pattern / C# / Fluent Interrface
public EmailBuilder()
{
_email = new Email();
}
https://riptutorial.com/ 18
public Email Build()
{
return _email;
}
}
Usage example:
The Builder pattern allows you to create an instance of a class with many optional variables in an
easy to read way.
This is all well and good if all of the parameters are necessary. What if there are a lot more
variables and/or some of them are optional? You don't want to create a large number of
constructors with each possible combination of required and optional parameters because it
becomes difficult to maintain and for developers to understand. You also may not want to have a
long list of parameters in which many may need to be entered as null by the user.
The Builder pattern creates an inner class called Builder that is used to instantiate only the desired
optional variables. This is done through methods for each optional variable which take the variable
type as a parameter and return a Builder object so that the methods can be chained with each
other. Any required variables are put into the Builder constructor so that they can not be left out.
The Builder also includes a method called build() which returns the object that it is in and must be
called at the end of the chain of method calls when building the object.
https://riptutorial.com/ 19
Following from the previous example, this code uses the Builder pattern for the Computer class.
https://riptutorial.com/ 20
}
}
This example shows how the builder pattern can allow a lot of flexibility in how a class is created
with fairly little effort. The Computer object can be implemented based on the callers desired
configuration in an easy to read manner with little effort.
Intent:
Separate the construction of a complex object from its representation so that the same
construction process can create different representations
Builder pattern is useful when you have few mandatory attributes and many optional attributes to
construct a object. To create an object with different mandatory and optional attributes, you have
to provide complex constructor to create the object.Builder pattern provides simple step-by-step
process to construct a complex object.
Different users in FaceBook have different attributes, which consists of mandatory attribute like
user name and optional attributes like UserBasicInfo and ContactInfo. Some users simply provide
basic info. Some users provide detailed information including Contact info. In absence of Builder
pattern, you have to provide a constructor with all mandatory and optional parameters. But Builder
pattern simplifies the construction process by providing simple step-by-step process to construct
the complex object.
Tips:
https://riptutorial.com/ 21
4. Return the same Builder object after setting optional attributes.
5. Provide build() method, which returns complex object
Code snippet:
import java.util.*;
class UserBasicInfo{
String nickName;
String birthDate;
String gender;
sb.append("Name:DOB:Gender:").append(nickName).append(":").append(birthDate).append(":").
append(gender);
return sb.toString();
}
}
class ContactInfo{
String eMail;
String mobileHome;
String mobileWork;
sb.append("email:mobile(H):mobile(W):").append(eMail).append(":").append(mobileHome).append(":").append
return sb.toString();
}
}
class FaceBookUser {
String userName;
UserBasicInfo userInfo;
ContactInfo contactInfo;
https://riptutorial.com/ 22
return userName;
}
public UserBasicInfo getUserBasicInfo(){
return userInfo;
}
public ContactInfo getContactInfo(){
return contactInfo;
}
sb.append("|User|").append(userName).append("|UserInfo|").append(userInfo).append("|ContactInfo|").appe
return sb.toString();
}
output:
https://riptutorial.com/ 23
Facebook user 2:|User|Ravindra|UserInfo|Name:DOB:Gender:sunrise:25-May-1975:M|ContactInfo|null
Facebook user 3:|User|Ravindra|UserInfo|Name:DOB:Gender:sunrise:25-May-
1975:M|ContactInfo|email:mobile(H):mobile(W):xxx@xyz.com:1111111111:2222222222
Explanation:
String userName;
UserBasicInfo userInfo;
ContactInfo contactInfo;
5. This example illustrates three different FaceBookUsers with different attributes, built from
Builder.
In above example, composition has been used instead of duplicating all attributes of
FaceBookUser in Builder class.
In creational patterns, we will first start with simple pattern like FactoryMethod and move towards
more flexible and complex patterns like AbstractFactory and Builder.
Java / Lombok
import lombok.Builder;
@Builder
public class Email {
Usage example:
Email.builder().to("email1@email.com")
.from("email2@email.com")
.subject("Email subject")
.body("Email content")
https://riptutorial.com/ 24
.build();
public Person(String salutation, String firstName, String middleName, String lastName, String
suffix, Address address, boolean isFemale, boolean isEmployed, boolean isHomewOwner) {
this.salutation = salutation;
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.suffix = suffix;
this.address = address;
this.isFemale = isFemale;
this.isEmployed = isEmployed;
this.isHomewOwner = isHomewOwner;
}
}
Old way
https://riptutorial.com/ 25
this.lastName = lastName;
return this;
}
Advanced Way:
https://riptutorial.com/ 26
}
Usage:
Refer: https://medium.com/beingprofessional/think-functional-advanced-builder-pattern-using-
lambda-284714b85ed5#.d9sryx3g9
https://riptutorial.com/ 27
Chapter 6: Chain of Responsibility
Examples
Chain of Responsibility example (Php)
A method called in one object will move up the chain of objects until one is found that can properly
handle the call. This particular example uses scientific experiments with functions that can just get
the title of the experiment, the experiments id or the tissue used in the experiment.
https://riptutorial.com/ 28
}
}
//This class and all further sub classes work in the same way as SubExperiment above
class SubSubExperiment extends AbstractExperiment {
private $experiment;
private $parentExperiment;
private $tissue;
function __construct($experiment_in, Experiment $parentExperiment_in) { //as above }
function getExperiment() { //same as above }
function getParentExperiment() { //same as above }
function getTissue() { //same as above }
}
https://riptutorial.com/ 29
Chapter 7: Command pattern
Examples
Command pattern example in Java
wikipedia definition:
In this way, Command pattern decouples Sender (Client) from Receiver through Invoker.
Invoker has complete knowledge of which Command to be executed and Command knows
which Receiver to be invoked to execute a particular operation.
Code snippet:
interface Command {
void execute();
}
class Receiver {
public void switchOn(){
System.out.println("Switch on from:"+this.getClass().getSimpleName());
}
https://riptutorial.com/ 30
}
class OnCommand implements Command{
private Receiver receiver;
output:
Switch on from:TV
Switch on from:DVDPlayer
Explanation:
In this example,
https://riptutorial.com/ 31
1. Command interface defines execute() method.
2. OnCommand is ConcreteCommand, which implements execute() method.
3. Receiver is the base class.
4. TV and DVDPlayer are two types of Receivers, which are passed to ConcreteCommand
like OnCommand.
5. Invoker contains Command. It's the key to de-couple Sender from Receiver.
6. Invoker receives OnCommand -> which calls Receiver (TV) to execute this command.
By using Invoker, you can switch on TV and DVDPlayer. If you extend this program, you switch off
both TV and DVDPlayer too.
https://riptutorial.com/ 32
Chapter 8: Composite pattern
Examples
Composite logger
The Composite pattern is a design pattern that allows to treat a group of objects as a single
instance of an object. It is one of the Gang of Four's structural design patterns.
Example below demonstrate how Composite can be used to log to multiple places using single
Log invocation. This approach adheres to SOLID principles because it allows you to add new
logging mechanism without violating Single responsibility principle (each logger has only one
responsibility) or Open/closed principle (You can add new logger that will log to new place by
adding new implementation and not by modifying existing ones).
https://riptutorial.com/ 33
var compositeLogger = new CompositeLogger(new ConsoleLogger(), new FileLogger());
compositeLogger.Log("some message"); //this will be invoked both on ConsoleLogger and
FileLogger
It is worth mentioning that composite loggers can be nested (one of the parameters to composite
loggers constructor can be another composite logger) creating tree-like structure.
https://riptutorial.com/ 34
Chapter 9: Composite pattern
Introduction
Composite lets clients treat individual objects and compositions of objects uniformly. For example
consider a program that manipulates a file system. Files are simple objects and folders are
composition of files and folders. However, for example, they both have size, name etc. functions. It
would be easier and more convenient to treat both file and folder objects uniformly by defining a
File System Resource Interface
Remarks
The composite pattern applies when there is a part-whole hierarchy of objects and a client needs
to deal with objects uniformly regardless of the fact that an object might be a leaf (simple object) or
a branch (composite object).
Examples
pseudocode for a dumb file manager
/*
* Component is an interface
* which all elements (files,
* folders, links ...) will implement
*/
class Component
{
public:
virtual int getSize() const = 0;
};
/*
* File class represents a file
* in file system.
*/
class File : public Component
{
public:
virtual int getSize() const {
// return file size
}
};
/*
* Folder is a component and
* also may contain files and
* another folders. Folder is a
* composition of components
*/
class Folder : public Component
{
https://riptutorial.com/ 35
public:
void addComponent(Component* aComponent) {
// mList append aComponent;
}
void removeComponent(Component* aComponent) {
// remove aComponent from mList
}
virtual int getSize() const {
int size = 0;
foreach(component : mList) {
size += component->getSize();
}
return size;
}
private:
list<Component*> mList;
};
https://riptutorial.com/ 36
Chapter 10: Data Access Object(DAO) design
pattern
Examples
Data Access Object J2EE design pattern with Java
In this design pattern data is accessed through classes containing methods to access data from
databases or other sources, which are called data access objects. Standard practice assumes that
there are POJO classes. DAO can be mixed with other Design Patterns to access data, such as
with MVC(model view controller), Command Patterns etc.
The following is an example of DAO design pattern. It has an Employee class, a DAO for
Employee called EmployeeDAO and an ApplicationView class to demonstrate the examples.
Employee.java
public Employee(){
EmployeeDAO
https://riptutorial.com/ 37
public List<Employee> getAllEmployees(){
return employeeList;
}
return employee;
}
ApplicationView.java
https://riptutorial.com/ 38
Hence we have an example where we see how to use Data Access Object design pattern.
https://riptutorial.com/ 39
Chapter 11: Decorator pattern
Introduction
Decorator pattern allows a user to add new functionality to an existing object without altering its
structure. This type of design pattern comes under structural pattern as this pattern acts as a
wrapper to existing class.
This pattern creates a decorator class which wraps the original class and provides additional
functionality keeping class methods signature intact.
Parameters
Parameter Description
Examples
VendingMachineDecorator
The Decorator pattern can be used to extend (decorate) the functionality of a certain object
statically, or in some cases at run-time, independently of other instances of the same class,
provided some groundwork is done at design time.
https://riptutorial.com/ 40
1. Component Interface: It defines an interface to execute particular operations
2. ConcreteComponent: It implements the operations defined in Component interface
3. Decorator (Abstract) : it is an abstract class, which extends the component interface. It
contains Component interface. In absence of this class, you need many sub-classes of
ConcreteDecorators for different combinations. Composition of component reduces un-
necessary sub-classes.
4. ConcreteDecorator: It holds the implementation of Abstract Decorator.
EDIT: Changed the example to reflect real world scenario of computing the price of Beverage by
adding one or more flavours like Sugar, Lemon etc( flavours are decorators)
}
public Beverage(String name){
this.name = name;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
protected void setPrice(int price){
this.price = price;
}
https://riptutorial.com/ 41
protected int getPrice(){
return price;
}
protected abstract void decorateBeverage();
}
class Tea extends Beverage{
public Tea(String name){
super(name);
setPrice(10);
}
public void decorateBeverage(){
System.out.println("Cost of:"+ name +":"+ price);
// You can add some more functionality
}
}
class Coffee extends Beverage{
public Coffee(String name){
super(name);
setPrice(15);
}
public void decorateBeverage(){
System.out.println("Cost of:"+ name +":"+ price);
// You can add some more functionality
}
}
abstract class BeverageDecorator extends Beverage {
protected Beverage beverage;
public BeverageDecorator(Beverage beverage){
this.beverage = beverage;
setName(beverage.getName()+"+"+getDecoratedName());
setPrice(beverage.getPrice()+getIncrementPrice());
}
public void decorateBeverage(){
beverage.decorateBeverage();
System.out.println("Cost of:"+getName()+":"+getPrice());
}
public abstract int getIncrementPrice();
public abstract String getDecoratedName();
}
class SugarDecorator extends BeverageDecorator{
public SugarDecorator(Beverage beverage){
super(beverage);
}
public void decorateBeverage(){
super.decorateBeverage();
decorateSugar();
}
public void decorateSugar(){
System.out.println("Added Sugar to:"+beverage.getName());
}
public int getIncrementPrice(){
return 5;
}
public String getDecoratedName(){
return "Sugar";
}
}
class LemonDecorator extends BeverageDecorator{
public LemonDecorator(Beverage beverage){
super(beverage);
https://riptutorial.com/ 42
}
public void decorateBeverage(){
super.decorateBeverage();
decorateLemon();
}
public void decorateLemon(){
System.out.println("Added Lemon to:"+beverage.getName());
}
public int getIncrementPrice(){
return 3;
}
public String getDecoratedName(){
return "Lemon";
}
}
output:
This example computes cost of beverage in Vending Machine after adding many flavours to the
beverage.
In above example:
Cost of Tea = 10, Lemon = 3 and Sugar = 5. If you make Sugar + Lemon + Tea, it costs 18.
Cost of Coffee =15, Lemon = 3 and Sugar = 5. If you make Sugar + Lemon + Coffee, it costs 23
By using same Decorator for both beverages ( Tea and Coffee ), the number of sub-classes have
been reduced. In absence of Decorator pattern, you should have different sub classes for different
combinations.
SugarLemonTea
SugarTea
LemonTea
https://riptutorial.com/ 43
SugarLemonCapaccuino
SugarCapaccuino
LemonCapaccuino
etc.
By using same Decorator for both beverages, the number of sub-classes have been reduced. It's
possible due to composition rather than inheritance concept used in this pattern.
1. Adapter provides a different interface to its subject. Proxy provides the same interface.
Decorator provides an enhanced interface.
3. Composite and Decorator have similar structure diagrams, reflecting the fact that both rely
on recursive composition to organize an open-ended number of objects
6. Decorator lets you change the skin of an object. Strategy lets you change the guts.
Caching Decorator
This example demonstrate how to add caching capabilities to DbProductRepository using Decorator
pattern. This approach adheres to SOLID principles because it allows you to add caching without
violating Single responsibility principle or Open/closed principle.
https://riptutorial.com/ 44
{
private readonly IProductRepository _decoratedRepository;
private readonly ICache _cache;
private const int ExpirationInHours = 1;
return product;
}
Usage:
Result of invoking GetProduct will be: retrieve product from cache (decorator responsibility), if
product was not in the cache proceed with invocation to DbProductRepositoryand retrieve product
from DB. After this product can be added to the cache so subsequent calls won't hit DB.
https://riptutorial.com/ 45
Chapter 12: Dependency Injection
Introduction
The general idea behind Dependency Injection is that you design your application around loosely
coupled components while adhering to the Dependency Inversion Principle. By not depending on
concrete implementations, allows to design highly flexible systems.
Remarks
The basic idea behind dependency injection is to create more loosely coupled code. When a
class, rather than newing up its own dependencies, takes in its dependencies instead, the class
becomes more simple to test as a unit (unit testing).
To further elaborate on loose coupling - the idea is that classes become dependent on
abstractions, rather than concretions. If class A depends on another concrete class B, then there is
no real testing of A without B. While this sort of test can be OK, it does not lend itself to unit
testable code. A loosely coupled design would define an abstraction IB (as an example) that class
A would depend on. IB can then be mocked to provide testable behavior, rather than relying on the
real implementation of B to be able to provide testable scenarios to A.
public class A
{
public void DoStuff()
{
B b = new B();
b.Foo();
}
}
In the above, class A depends on B. There is no testing A without the concrete B. While this is fine
in an integration testing scenario, it is difficult to unit test A.
public interface IB
{
void Foo();
}
public class A
{
private readonly IB _iB;
https://riptutorial.com/ 46
public void DoStuff()
{
_b.Foo();
}
}
The two implementations seem quite similar, there is however an important difference. Class A is
no longer directly dependent on class B, it is now dependent on IB. Class A no longer has the
responsibility of newing up its own depedencies - they must now be provided to A.
Examples
Setter injection (C#)
https://riptutorial.com/ 47
injection
https://riptutorial.com/ 48
Chapter 13: Facade
Examples
Real world facade (C#)
facade.Execute();
}
}
// the facade puts all the individual pieces together, as its single responsibility.
public void Execute()
{
var dataLocationForExport = _determineExportData.GetDataLocation();
var rawData = _getRawData.GetDataFromDb(dataLocationForExport);
var transformedData = _transformData.TransformRawToExportableObject(rawData);
_createExcel.GenerateExcel("myFilename.xlsx");
}
}
Facade is structural design pattern. It hides the complexities of large system and provides a
simple interface to client.
Client uses only Facade and it's not worried about inter dependencies of sub-systems.
Structure:
https://riptutorial.com/ 49
Real world example:
Think of some travel booking sites like makemytrip, cleartrip which offers services to book Trains,
Flights and Hotels.
Code snippet:
import java.util.*;
enum BookingType {
Flight,Train,Hotel,Flight_And_Hotel,Train_And_Hotel;
};
public TravelFacade(){
flightBooking = new FlightBooking();
trainBooking = new TrainBooking();
hotelBooking = new HotelBooking();
}
public void book(BookingType type, BookingInfo info){
switch(type){
case Flight:
// book flight;
flightBooking.bookFlight(info);
return;
case Hotel:
// book hotel;
hotelBooking.bookHotel(info);
return;
case Train:
// book Train;
https://riptutorial.com/ 50
trainBooking.bookTrain(info);
return;
case Flight_And_Hotel:
// book Flight and Hotel
flightBooking.bookFlight(info);
hotelBooking.bookHotel(info);
return;
case Train_And_Hotel:
// book Train and Hotel
trainBooking.bookTrain(info);
hotelBooking.bookHotel(info);
return;
}
}
}
class BookingInfo{
String source;
String destination;
Date fromDate;
Date toDate;
List<PersonInfo> list;
}
class PersonInfo{
String name;
int age;
Address address;
}
class Address{
}
class FlightBooking{
public FlightBooking(){
}
public void bookFlight(BookingInfo info){
}
}
class HotelBooking{
public HotelBooking(){
}
public void bookHotel(BookingInfo info){
}
}
class TrainBooking{
public TrainBooking(){
}
public void bookTrain(BookingInfo info){
}
}
Explanation:
https://riptutorial.com/ 51
2. TravelFacade offers a simple interface to book one of below options
Flight Booking
Train Booking
Hotel Booking
Flight + Hotel booking
Train + Hotel booking
flightBooking.bookFlight
trainBooking.bookTrain(info);
hotelBooking.bookHotel(info);
4. In this way, TravelFacade provides simpler and easier API with-out exposing sub-system
APIs.
https://riptutorial.com/ 52
Chapter 14: Factory
Remarks
Provide an interface for creating families of related or dependent objects without
specifying their concrete classes.
-- GOF 1994
Examples
Simple factory (Java)
A factory decreases coupling between code that needs to create objects from object creation
code. Object creation is not made explicitly by calling a class constructor but by calling some
function that creates the object on behalf the caller. A simple Java example is the following one:
interface Car {
}
https://riptutorial.com/ 53
In this example, user just gives some hint about what he needs and the factory is free to construct
something appropriate. It is a dependency inversion: the implementor of Car concept is free to
return an appropriate concrete Car requested by the user which in turn doesn't know the details of
the concrete object built.
This is a simple example of how factory works, of course in this example it is always possible to
instantiate concrete classes; but one can prevent it by hiding concrete classes in a package, such
that user is forced to use the factory.
Abstract factory pattern provides a way to obtain an coherent collection of objects through a
collection of factories functions. As for every pattern, coupling is reduced by abstracting the way a
set of objects are created, so that the user code is unaware of the many details of the objects he
needs.
The following C++ example illustrates how to obtain different kind of objects of the same
(hypothetical) GUI family:
#include <iostream>
/* Abstract definitions */
class GUIComponent {
public:
virtual ~GUIComponent() = default;
virtual void draw() const = 0;
};
class Frame : public GUIComponent {};
class Button : public GUIComponent {};
class Label : public GUIComponent {};
class GUIFactory {
public:
virtual ~GUIFactory() = default;
virtual std::unique_ptr<Frame> createFrame() = 0;
virtual std::unique_ptr<Button> createButton() = 0;
virtual std::unique_ptr<Label> createLabel() = 0;
static std::unique_ptr<GUIFactory> create(const std::string& type);
};
/* Windows support */
class WindowsFactory : public GUIFactory {
private:
class WindowsFrame : public Frame {
public:
void draw() const override { std::cout << "I'm a Windows-like frame" << std::endl; }
};
class WindowsButton : public Button {
public:
void draw() const override { std::cout << "I'm a Windows-like button" << std::endl; }
};
class WindowsLabel : public Label {
public:
https://riptutorial.com/ 54
void draw() const override { std::cout << "I'm a Windows-like label" << std::endl; }
};
public:
std::unique_ptr<Frame> createFrame() override { return std::make_unique<WindowsFrame>(); }
std::unique_ptr<Button> createButton() override { return std::make_unique<WindowsButton>();
}
std::unique_ptr<Label> createLabel() override { return std::make_unique<WindowsLabel>(); }
};
/* Linux support */
class LinuxFactory : public GUIFactory {
private:
class LinuxFrame : public Frame {
public:
void draw() const override { std::cout << "I'm a Linux-like frame" << std::endl; }
};
class LinuxButton : public Button {
public:
void draw() const override { std::cout << "I'm a Linux-like button" << std::endl; }
};
class LinuxLabel : public Label {
public:
void draw() const override { std::cout << "I'm a Linux-like label" << std::endl; }
};
public:
std::unique_ptr<Frame> createFrame() override { return std::make_unique<LinuxFrame>(); }
std::unique_ptr<Button> createButton() override { return std::make_unique<LinuxButton>(); }
std::unique_ptr<Label> createLabel() override { return std::make_unique<LinuxLabel>(); }
};
/* User code */
void buildInterface(GUIFactory& factory) {
auto frame = factory.createFrame();
auto button = factory.createButton();
auto label = factory.createLabel();
frame->draw();
button->draw();
label->draw();
}
$ ./abstractfactory windows
I'm a Windows-like frame
I'm a Windows-like button
I'm a Windows-like label
$ ./abstractfactory linux
I'm a Linux-like frame
https://riptutorial.com/ 55
I'm a Linux-like button
I'm a Linux-like label
Factories can be used in conjunction with Inversion of Control (IoC) libraries too.
• The typical use case for such a factory is when we want to create an object based on
parameters that are not known until run-time (such as the current User).
• In these cases it can be sometimes be difficult (if not impossible) to configure the IoC library
alone to handle this kind of runtime contextual information, so we can wrap it in a factory.
Example
• Suppose we have a User class, whose characteristics (ID, Security clearance level, etc.), are
unknown until runtime (since the current user could be anyone who uses the application).
• We need to take the current User and obtain an ISecurityToken for them, which can then be
used to check if the user is allowed to perform certain actions or not.
• The implementation of ISecurityToken will vary depending on the level of the User - in other
words, ISecurityToken uses polymorphism.
In this case, we have two implementations, which also use Marker Interfaces to make it easier to
identify them to the IoC library; the IoC library in this case is just made up and identified by the
abstraction IContainer.
Note also that many modern IoC factories have native capabilities or plugins that allow
auto-creation of factories as well as avoiding the need for marker interfaces as shown
below; however since not all do, this example caters to a simple, lowest common
functionality concept.
https://riptutorial.com/ 56
{
public bool IsAllowedTo(PerformAction action)
{
//Super users can perform all actions
return true;
}
}
Next we will create a SecurityToken factory, which will take as a dependency our IContainer
the consuming code can use it to get the correct token at runtime:
In this way we benefit from the encapsulation provided by the factory and also from the
lifecycle management provided by the IoC library.
https://riptutorial.com/ 57
An Abstract Factory
An abstract factory is used to provide an interface for creating families of related objects, without
specifying concrete classes and can be used to hide platform specific classes.
interface Tool {
void use();
}
interface ToolFactory {
Tool create();
}
@Override
public void use() {
// Do something...
}
}
@Override
public Tool create() {
// Maybe additional logic to setup...
return new GardenTool();
}
}
@Override
public void use() {
// Do something...
https://riptutorial.com/ 58
}
}
@Override
public Tool create() {
// Maybe additional logic to setup...
return new FarmTool();
}
}
Then a supplier/producer of some sort would be used which would be passed information that
would allow it to give back the correct type of factory implementation:
switch (type) {
case FARM:
factory = new FarmToolFactory();
break;
case GARDEN:
factory = new GardenToolFactory();
break;
} // Could potentially add a default case to handle someone passing in null
return factory;
}
}
Intent:
Define an interface for creating an object, but let sub classes decide which class to instantiate.
Factory Method lets a class defer instantiation to sub classes.
UML diagram:
https://riptutorial.com/ 59
Product: It defines an interface of the objects the Factory method creates.
Problem statement: Create a Factory of Games by using Factory Methods, which defines the
game interface.
Code snippet:
import java.util.HashMap;
https://riptutorial.com/ 60
System.out.println("For each opponent, place 10 coins");
System.out.println("Start Checkers game");
System.out.println("---------------------------------------");
}
}
class Ludo implements Game{
public Ludo(){
createGame();
}
public void createGame(){
System.out.println("---------------------------------------");
System.out.println("Create Ludo game");
System.out.println("Opponents:2 or 3 or 4");
System.out.println("For each opponent, place 4 coins");
System.out.println("Create two dices with numbers from 1-6");
System.out.println("Start Ludo game");
System.out.println("---------------------------------------");
}
}
public GameFactory(){
games.put(Chess.class.getName(),new Chess());
games.put(Checkers.class.getName(),new Checkers());
games.put(Ludo.class.getName(),new Ludo());
}
public Game getGame(String gameName){
return games.get(gameName);
}
}
https://riptutorial.com/ 61
output:
1. Game is the interface for all type of games. It defines complex method: createGame()
2. Chess, Ludo, Checkers are different variants of games, which provide implementation to
createGame()
6. getGame in GameFactory accepts a game name and returns corresponding Game object.
When to use:
1. Factory: When you don't want to expose object instantiation logic to the client/caller
2. Abstract Factory: When you want to provide interface to families of related or dependent
objects without specifying their concrete classes
3. Factory Method: To define an interface for creating an object, but let the sub-classes decide
which class to instantiate
1. Design start out using Factory Method (less complicated, more customizable, subclasses
proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more
complex) as the designer discovers where more flexibility is needed
https://riptutorial.com/ 62
2. Abstract Factory classes are often implemented with Factory Methods, but they can also
be implemented using Prototype
In simple words:
A Flyweight factory that for a given, already known, key will always give the same object as
response. For new keys will create the instance and return it.
Implementation:
Extra Notes
I would recommend to add to this solution the use of an IoC Container (as explained in a different
example here) instead of creating your own new instances. One can do it by adding a new
registration for the TResult to the container and then resolving from it (instead of the dictionary in
https://riptutorial.com/ 63
the example).
Factory method
The Factory method pattern is a creational pattern that abstracts away the instantiation logic of an
object in order to decouple the client code from it.
When a factory method belongs to a class that is an implementation of another factory pattern
such as Abstract factory then it is usually more appropriate to reference the pattern implemented
by that class rather than the Factory method pattern.
The Factory method pattern is more commonly referenced when describing a factory method that
belongs to a class which is not primarily a factory.
For instance, it may be advantageous to place a factory method on an object that represents a
domain concept if that object encapsulates some state that would simplify the creation process of
another object. A factory method may also lead to a design that is more aligned with the
Ubiquitous Language of a specific context.
https://riptutorial.com/ 64
Chapter 15: Iterator Pattern
Examples
The Iterator Pattern
Collections are one of the most commonly used data structures in software engineering. A
Collection is just a group of objects. A collection can be a List, an array, a map, a tree or anything.
So, a collection should provide some way to access its elements without exposing its internal
structure. We should be able to traverse it in a same irrespective of type of collection it is.
The iterator pattern idea is to take the responsibility of accessing the object of a collection and put
it in an iterator object. The iterator object in return will maintain the order of iteration, keep a track
of current item and must be having a way to fetch the next element.
Usually, the collection class carries two components: the class itself, and it's Iterator.
https://riptutorial.com/ 65
int index;
@Override
public boolean hasNext() {
return index < fruits.length;
}
@Override
public Object next() {
if(this.hasNext()) {
return names[index++];
}
return null;
}
}
}
https://riptutorial.com/ 66
Chapter 16: lazy loading
Introduction
eager loading is expensive or the object to be loaded might not be needed at all
Examples
JAVA lazy loading
Heavy.class
/**
*
* Heavy objects are expensive to create.
*
*/
public class Heavy {
/**
* Constructor
*/
public Heavy() {
LOGGER.info("Creating Heavy ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LOGGER.error("Exception caught.", e);
}
LOGGER.info("... Heavy created");
}
}
HolderNaive.class
/**
*
* Simple implementation of the lazy loading idiom. However, this is not thread safe.
*
*/
public class HolderNaive {
https://riptutorial.com/ 67
private Heavy heavy;
/**
* Constructor
*/
public HolderNaive() {
LOGGER.info("HolderNaive created");
}
/**
* Get heavy object
*/
public Heavy getHeavy() {
if (heavy == null) {
heavy = new Heavy();
}
return heavy;
}
}
https://riptutorial.com/ 68
Chapter 17: Mediator Pattern
Examples
Mediator pattern example in java
Mediator pattern defines an object (Mediator) that encapsulates how a set of objects interact. It
enables many-to-many communication.
UML diagram:
Key components:
Colleague: Is an abstract class, which defines the events to be communicated between Colleagues
ConcreteColleague:
Implements the notification operations received through Mediator, which has
been generated by other Colleague
A mesh network is a network topology in which each node relays data for the network. All mesh
nodes cooperate in the distribution of data in the network.
If a new computer is added Or existing computer is removed, all other computers in that network
should know about these two events.
Code snippet:
https://riptutorial.com/ 69
import java.util.List;
import java.util.ArrayList;
public NetworkMediator(){
https://riptutorial.com/ 70
}
}
public void unregister(Colleague colleague){
colleagues.remove(colleague);
for (Colleague other : colleagues){
other.receiveUnRegisterNotification(colleague);
}
}
}
output:
Explanation:
1. Eagle is added to network at first through register event. No notifications to any other
colleagues since Eagle is the first one.
2. When Ostrich is added to the network, Eagle is notified : Line 1 of output is rendered now.
3. When Penguin is added to network, both Eagle and Ostrich have been notified : Line 2 and
Line 3 of output is rendered now.
4. When Eagle left the network through unregister event, both Ostrich and Penguin have been
notified. Line 4 and Line 5 of output is rendered now.
https://riptutorial.com/ 71
Chapter 18: Monostate
Remarks
As a side note, a few advantages of the Monostate pattern over the Singleton:
Examples
The Monostate Pattern
The Monostate pattern is usually referred to as syntactic sugar over the Singleton pattern or as a
conceptual Singleton.
It avoids all the complications of having a single instance of a class, but all the instances use the
same data.
This is accomplished mostly by using static data members.
One of the most important feature is that it's absolutely transparent for the users, that are
completely unaware they are working with a Monostate. Users can create as many instances of a
Monostate as they want and any instance is good as another to access the data.
The Monostate class comes usually with a companion class that is used to update the settings if
needed.
struct Settings {
Settings() {
if(!initialized) {
initialized = true;
// load from file or db or whatever
// otherwise, use the SettingsEditor to initialize settings
Settings::width_ = 42;
Settings::height_ = 128;
}
}
private:
friend class SettingsEditor;
https://riptutorial.com/ 72
static std::size_t width_;
static std::size_t height_;
};
struct SettingsEditor {
void width(std::size_t value) noexcept { Settings::width_ = value; }
void height(std::size_t value) noexcept { Settings::height_ = value; }
};
static {
width = 42;
height = 128;
}
}
Monostate-based hierarchies
In contrasto to the Singleton, the Monostate is suitable to be inherited to extend its functionalities, as
long as member methods are not static.
It follows a minimal example in C++:
struct Settings {
virtual std::size_t width() const noexcept { return width_; }
virtual std::size_t height() const noexcept { return height_; }
private:
static std::size_t width_;
static std::size_t height_;
};
std::size_t Settings::width_{0};
https://riptutorial.com/ 73
std::size_t Settings::height_{0};
https://riptutorial.com/ 74
Chapter 19: Multiton
Remarks
Multitonitis
Same as Singleton, Multiton can be considered a bad practice. However, there are times when
you can use it wisely (for example, if you building a system like ORM/ODM to persist multiple
objects).
Examples
Pool of Singletons (PHP example)
This is an example of how common Multiton abstract Pool class can be created:
/**
* Get class name of lately binded class
*
* @return string
*/
final protected static function getClassName()
{
return get_called_class();
}
/**
* Instantiates a calling class object
*
* @return static
*/
public static function getInstance()
{
$className = static::getClassName();
if( !isset(self::$instances[$className]) ) {
self::$instances[$className] = new $className;
}
return self::$instances[$className];
}
https://riptutorial.com/ 75
/**
* Deletes a calling class object
*
* @return void
*/
public static function deleteInstance()
{
$className = static::getClassName();
if( isset(self::$instances[$className]) )
unset(self::$instances[$className]);
}
/*-------------------------------------------------------------------------
| Seal methods that can instantiate the class
|------------------------------------------------------------------------*/
This pattern can be used to contain a registered Pools of Singletons, each distinguished by unique
ID:
/**
* @param string $id
*/
final protected function __construct($id) {}
/**
* Get class name of lately binded class
*
* @return string
*/
final protected static function getClassName()
{
return get_called_class();
}
/**
* Instantiates a calling class object
*
* @return static
https://riptutorial.com/ 76
*/
public static function getInstance($id)
{
$className = static::getClassName();
if( !isset(self::$instances[$className]) ) {
self::$instances[$className] = [$id => new $className($id)];
} else {
if( !isset(self::$instances[$className][$id]) ) {
self::$instances[$className][$id] = new $className($id);
}
}
return self::$instances[$className][$id];
}
/**
* Deletes a calling class object
*
* @return void
*/
public static function unsetInstance($id)
{
$className = static::getClassName();
if( isset(self::$instances[$className]) ) {
if( isset(self::$instances[$className][$id]) ) {
unset(self::$instances[$className][$id]);
}
if( empty(self::$instances[$className]) ) {
unset(self::$instances[$className]);
}
}
}
/*-------------------------------------------------------------------------
| Seal methods that can instantiate the class
|------------------------------------------------------------------------*/
This is simplified form of pattern that can be used for ORM to store several entities of a given type.
https://riptutorial.com/ 77
Chapter 20: MVC, MVVM, MVP
Remarks
It can be argued that MVC and related patterns are actually software architecture patterns rather
than software design patterns.
Examples
Model View Controller (MVC)
1. What is MVC?
The Model View Controller (MVC) Pattern is a design pattern most commonly used for creating
user interfaces. The major advantage of MVC is that it separates:
The primary use case for MVC is in Graphical User Interface (GUI) programming. The View
component listens to the Model component for changes. The Model acts as a broadcaster; when
there is a change mode to the Model, it broadcasts its changes to the View and the Controller. The
Controller is used by the View to modify the Model Component.
3. Implementation
Consider the following implementation of MVC, where we have a Model class called Animals, a
View class called DisplayAnimals, and a controller class called AnimalController. The example
below is a modified version of the tutorial on MVC from Design Patterns - MVC Pattern.
/* Model class */
public class Animals {
private String name;
private String gender;
https://riptutorial.com/ 78
public void setGender(String gender) {
this.gender = gender;
}
}
/* View class */
public class DisplayAnimals {
public void printAnimals(String tag, String gender) {
System.out.println("My Tag name for Animal:" + tag);
System.out.println("My gender: " + gender);
}
}
/* Controller class */
public class AnimalController {
private Animal model;
private DisplayAnimals view;
4. Sources used:
Model–view–controller
1. What is MVVM?
The Model View ViewModel (MVVM) pattern is a design pattern most commonly used for creating
https://riptutorial.com/ 79
user interfaces. It is derived from the the popular "Model View Controller" (MVC) pattern. The
major advantage of MVVM is that it separates:
The primary use case of MVVM is Graphical User Interface (GUI) programming. It is used to
simply event-driven programming of user interfaces by separating the view layer from the backend
logic managing the data.
In Windows Presentation Foundation (WPF), for example, the view is designed using the
framework markup language XAML. The XAML files are bound to ViewModels using data binding.
This way the view is only responsible for presentation and the viewmodel is only responsible for
managing application state by working on the data in the model.
3. Implementation
Consider the following implementation of MVVM using C# .Net and WPF. We have a Model class
called Animals, a View class implemented in Xaml and a ViewModel called AnimalViewModel. The
example below is a modified version of the tutorial on MVC from Design Patterns - MVC Pattern.
Look how the Model does not know about anything, the ViewModel only knows about the Model
and the View only knows about the ViewModel.
The OnNotifyPropertyChanged-event enables updating both the model and the view so that when
you enter something in the textbox in the view the model is updated. And if something updates the
model, the view is updated.
/*Model class*/
public class Animal
{
public string Name { get; set; }
/*ViewModel class*/
public class AnimalViewModel : INotifyPropertyChanged
{
private Animal _model;
public AnimalViewModel()
{
_model = new Animal {Name = "Cat", Gender = "Male"};
}
https://riptutorial.com/ 80
{
get { return _model.Name; }
set
{
_model.Name = value;
OnPropertyChanged("AnimalName");
}
}
<Window.DataContext>
<viewModel:AnimalViewModel/>
</Window.DataContext>
<StackPanel>
<TextBox Text="{Binding AnimalName}" Width="120" />
<TextBox Text="{Binding AnimalGender}" Width="120" />
</StackPanel>
</Window>
4. Sources used:
Model–view–viewmodel
https://riptutorial.com/ 81
Read MVC, MVVM, MVP online: https://riptutorial.com/design-patterns/topic/7405/mvc--mvvm--
mvp
https://riptutorial.com/ 82
Chapter 21: Null Object pattern
Remarks
Null Object is an object with no referenced value or with defined neutral behaviour. Its purpose is
to remove the need of null pointer/reference check.
Examples
Null Object Pattern (C++)
class ILogger {
virtual ~ILogger() = default;
virtual Log(const std::string&) = 0;
};
Instead of
void doJobWithoutLogging()
{
doJob(nullptr);
}
https://riptutorial.com/ 83
// ...
logger.Log("[doJob]:Step 2");
// ...
logger.Log("[doJob]:End");
}
void doJobWithoutLogging()
{
NullLogger logger;
doJob(logger);
}
Given an interface:
Because null objects have no state, it makes sense to use a enum singleton for it, so given a null
object implemented like so:
@Override
public void log(String message) {
// Do nothing
}
}
https://riptutorial.com/ 84
logger.log("[doJob]:Step 1");
// ...
logger.log("[doJob]:Step 2");
// ...
logger.log("[doJob]:Step 3");
}
https://riptutorial.com/ 85
Chapter 22: Observer
Remarks
Examples
Observer / Java
The observer pattern lets users of a class subscribe to events that happen when this class
processes data etc. and be notified when these event occur. In the following example we create a
processing class and an observer class which will be notified while processing a phrase - if it finds
words that are longer than 5 letters.
The LongWordsObserver interface defines the observer. Implement this interface in order to register
an observer to events.
The WordEvent class is the event that will be sent to the observer classes once certain events occur
(in this case, long words were found)
// An event class which contains the long word that was found
public class WordEvent {
https://riptutorial.com/ 86
private String word;
The PhraseProcessor class is the class that processes the given phrase. It allows observers to be
registered using the addObserver method. Once long words are found, these observers will be
called using an instance of the WordEvent class.
import java.util.ArrayList;
import java.util.List;
// register an observer
public void addObserver(LongWordsObserver observer) {
observers.add(observer);
}
// the main method - process a phrase and look for long words. If such are found,
// notify all the observers
public void process(String phrase) {
for (String word : phrase.split(" ")) {
if (word.length() > 5) {
informObservers(word);
}
}
}
}
The LongWordsExample class shows how to register observers, call the process method and receive
alerts when long words were found.
import java.util.ArrayList;
import java.util.List;
https://riptutorial.com/ 87
// create the PhraseProcessor class
PhraseProcessor processor = new PhraseProcessor();
IObserver<T> and IObservable<T> interfaces can be used to implement observer pattern in .NET
https://riptutorial.com/ 88
public Unsubscriber(IList<IObserver<Stock>> observers, IObserver<Stock> observer) {
_observers = observers;
_observer = observer;
}
Usage
...
var provider = new StockTrader();
var i1 = new Investor();
i1.Subscribe(provider);
var i2 = new Investor();
i2.Subscribe(provider);
provider.Trade(new Stock());
provider.Trade(new Stock());
provider.Trade(null);
provider.End();
...
https://riptutorial.com/ 89
Chapter 23: Open Close Principle
Introduction
The Open Close Principle states that the design and writing of the code should be done in a way
that new functionality should be added with minimum changes in the existing code. The design
should be done in a way to allow the adding of new functionality as new classes, keeping as much
as possible existing code unchanged. Software entities like classes, modules and functions should
be open for extension but closed for modifications.
Remarks
Like every principle Open Close Principle is only a principle. Making a flexible design involves
additional time and effort spent for it and it introduce new level of abstraction increasing the
complexity of the code. So this principle should be applied in those area which are most likely to
be changed. There are many design patterns that help us to extend code without changing it, for
example decorator.
Examples
Open Close Principle violation
/*
* This design have some major issues
* For each new shape added the unit testing
* of the GraphicEditor should be redone
* When a new type of shape is added the time
* for adding it will be high since the developer
* who add it should understand the logic
* of the GraphicEditor.
* Adding a new shape might affect the existing
* functionality in an undesired way,
* even if the new shape works perfectly
*/
class GraphicEditor {
public void drawShape(Shape s) {
if (s.m_type==1)
drawRectangle(s);
else if (s.m_type==2)
drawCircle(s);
}
public void drawCircle(Circle r) {....}
public void drawRectangle(Rectangle r) {....}
}
class Shape {
int m_type;
}
https://riptutorial.com/ 90
class Rectangle extends Shape {
Rectangle() {
super.m_type=1;
}
}
/*
* For each new shape added the unit testing
* of the GraphicEditor should not be redone
* No need to understand the sourcecode
* from GraphicEditor.
* Since the drawing code is moved to the
* concrete shape classes, it's a reduced risk
* to affect old functionallity when new
* functionallity is added.
*/
class GraphicEditor {
public void drawShape(Shape s) {
s.draw();
}
}
class Shape {
abstract void draw();
}
https://riptutorial.com/ 91
Chapter 24: Prototype Pattern
Introduction
The Prototype pattern is a creational pattern that creates new objects by cloning existing prototype
object. The prototype pattern speeds up the instantiation of classes when copying objects is faster.
Remarks
The prototype pattern is a creational design pattern. It is used when the type of objects to create is
determined by a prototypical instance, which is "cloned" to produce new objects.
Examples
Prototype Pattern (C++)
class IPrototype {
public:
virtual ~IPrototype() = default;
private:
virtual IPrototype* DoClone() const = 0;
virtual IPrototype* DoCreate() const = 0;
};
https://riptutorial.com/ 92
public:
auto Clone() const { return std::unique_ptr<ChildA>{DoClone()}; }
auto Create() const { return std::unique_ptr<ChildA>{DoCreate()}; }
private:
// Use covariant return type :)
ChildA* DoClone() const override { return new ChildA(*this); }
ChildA* DoCreate() const override { return new ChildA; }
};
That allows to construct the derived class from a base class pointer:
ChildA childA;
A& a = childA;
IPrototype& prototype = a;
The prototype pattern can be implemented using the ICloneable interface in .NET.
class Spoon {
}
class DessertSpoon : Spoon, ICloneable {
...
public object Clone() {
return this.MemberwiseClone();
}
}
class SoupSpoon : Spoon, ICloneable {
...
public object Clone() {
return this.MemberwiseClone();
}
}
In the classical languages like Java, C# or C++ we start by creating a class and then we can
create new objects from the class or we can extend the class.
In JavaScript first we create an object, then we can augment the object or create new objects from
it. So i think, JavaScript demonstrates actual prototype than the classical language.
Example :
https://riptutorial.com/ 93
var myApp = myApp || {};
myApp.Customer.prototype = {
read: function (id) {
return "this is the customer with id = " + id;
},
update: function () {
return "customer updated";
},
remove: function () {
return "customer removed";
}
};
Here, we create an object named Customer, and then without creating new object we extended the
existing Customer object using prototype keyword. This technique is known as Prototype Pattern.
https://riptutorial.com/ 94
Chapter 25: Publish-Subscribe
Examples
Publish-Subscribe in Java
The publisher-subscriber is a familiar concept given the rise of YouTube, Facebook and other
social media services. The basic concept is that there is a Publisher who generates content and a
Subscriber who consumes content. Whenever the Publisher generates content, each Subscriber is
notified. Subscribers can theoretically be subscribed to more than one publisher.
Usually there is a ContentServer that sits between publisher and subscriber to help mediate the
messaging
private ContentServer() {
this.subscriberLists = new Hashtable<>();
}
https://riptutorial.com/ 95
public Subscriber(Topic...topics) {
for (Topic t : topics) {
ContentServer.getInstance().registerSubscriber(this, t);
}
}
Usually, the pub-sub design pattern is implemented with a multithreaded view in mind. One of the
more common implementations sees each Subscriber as a separate thread, with the ContentServer
managing a thread pool
Publishers and subscribers don't need to know each other. They simply communicate with the
help of message queues.
(function () {
var data;
setTimeout(function () {
data = 10;
$(document).trigger("myCustomEvent");
}, 2000);
$(document).on("myCustomEvent", function () {
console.log(data);
});
})();
Here we published a custom event named myCustomEvent and subscribed on that event. So
they don't need to know each other.
https://riptutorial.com/ 96
Chapter 26: Repository Pattern
Remarks
About the implementation of IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter):
The idea of this is to use Expressions like i => x.id == 17 to write generic requests. It is a way to
query data without using the specific query language of your technology. The implementation is
rather extensive, therefore you might want to consider other alternatives, like specific methods on
your implemented repositories: An imaginary CompanyRepository could provide the method
GetByName(string name).
Examples
Read-only repositories (C#)
A repository pattern can be used to encapsulate data storage specific code in designated
components. The part of your application, that needs the data will only work with the repositories.
You will want to create a repository for each combination of item you store and your database
technology.
Read only repositories can be used to create repositories that are not allowed to manipulate data.
The interfaces
public interface IReadOnlyRepository<TEntity, TKey> : IRepository
{
IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter);
https://riptutorial.com/ 97
where TModel : class
{
public ElasticReadRepository()
{
Client = Connect();
}
Using this implementation, you can now create specific Repositories for the items you want to
store or access. When using elastic search, it is common, that some components should only read
the data, thus read-only repositories should be used.
Repository interface;
https://riptutorial.com/ 98
void Insert(ICollection<T> entities);
void Delete(T entity);
void Delete(ICollection<T> entity);
IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
IQueryable<T> GetAll();
T GetById(int id);
}
Generic repository;
https://riptutorial.com/ 99
var hotel = new Hotel("Hotel 1", "42 Wallaby Way, Sydney");
hotelRepo.Insert(hotel);
db.SaveChanges();
https://riptutorial.com/ 100
Chapter 27: Singleton
Remarks
The Singleton design pattern is sometimes regarded as "Anti pattern". This is due to the fact that it
has some problems. You have to decide for yourself if you think it is appropriate to use it. This
topic has been discussed several times on StackOverflow.
See: http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons
Examples
Singleton (C#)
Singletons are used to ensure that only one instance of an object is being created. The singleton
allows only a single instance of itself to be created which means it controls its creation. The
singleton is one of the Gang of Four design patterns and is a creational pattern.
private Singleton()
{
}
return _instance;
}
https://riptutorial.com/ 101
Jon Skeet provides the following implementation for a lazy, thread-safe singleton:
private Singleton()
{
}
}
Singleton (Java)
Singletons in Java are very similar to C#, being as both languages are object orientated. Below is
an example of a singleton class, where only one version of the object can be alive during the
program's lifetime (Assuming the program works on one thread)
private SingletonExample() { }
if (_instance == null) {
_instance = new SingletonExample();
}
return _instance;
}
}
private SingletonThreadSafeExample () { }
https://riptutorial.com/ 102
}
}
Java also have an object called ThreadLocal, which creates a single instance of an object on a
thread by thread basis. This could be useful in applications where each thread need its own
version of the object
private SingletonThreadLocalExample () { }
Here is also a Singleton implementation with enum (containing only one element):
Any Enum class implementation ensures that there is only one instance of its each element will
exist.
Bill Pugh Singleton Pattern is the most widely used approach for Singleton class as it doesn’t
require synchronization
private SingletonExample(){}
with using private inner static class the holder is not loaded to memory until someone call the
getInstance method. Bill Pugh solution is thread safe and it doesn't required synchronization.
https://riptutorial.com/ 103
There are more Java singleton examples in the Singletons topic under the Java documentation
tag.
Singleton (C++)
As per Wiki : In software engineering, the singleton pattern is a design pattern that restricts the
instantiation of a class to one object.
This is required to create exactly one object to coordinate actions across the system.
class Singleton
{
// Private constructor so it can not be arbitrarily created.
Singleton()
{}
// Disable the copy and move
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
public:
If you are developing a client-server application, you need single instrance of ConnectionManager,
which manages the life cycle of client connections.
closeConnection : Close the connection either from event triggered by Client or Server
broadcastMessage : Some times, you have to send a message to all subscribed client connections.
I am not providing complete implementation of source code since example will become very
lengthy. At high level, the code will be like this.
import java.util.*;
import java.net.*;
https://riptutorial.com/ 104
/* Lazy Singleton - Thread Safe Singleton without synchronization and volatile constructs */
final class LazyConnectionManager {
private Map<String,Connection> connections = new HashMap<String,Connection>();
private LazyConnectionManager() {}
public static LazyConnectionManager getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final LazyConnectionManager INSTANCE = new LazyConnectionManager();
}
https://riptutorial.com/ 105
Other practical use cases for Singletons:
Static initialization is suitable for most situations. When your application must delay the
instantiation, use a non-default constructor or perform other tasks before the instantiation, and
work in a multithreaded environment, you need a different solution. Cases do exist, however, in
which you cannot rely on the common language runtime to ensure thread safety, as in the Static
Initialization example. In such cases, you must use specific language capabilities to ensure that
only one instance of the object is created in the presence of multiple threads. One of the more
common solutions is to use the Double-Check Locking [Lea99] idiom to keep separate threads
from creating new instances of the singleton at the same time.
The following implementation allows only a single thread to enter the critical area, which the lock
block identifies, when no instance of Singleton has yet been created:
using System;
private Singleton() {}
return instance;
}
}
}
This approach ensures that only one instance is created and only when the instance is needed.
Also, the variable is declared to be volatile to ensure that assignment to the instance variable
completes before the instance variable can be accessed. Lastly, this approach uses a syncRoot
instance to lock on, rather than locking on the type itself, to avoid deadlocks.
This double-check locking approach solves the thread concurrency problems while avoiding an
https://riptutorial.com/ 106
exclusive lock in every call to the Instance property method. It also allows you to delay
instantiation until the object is first accessed. In practice, an application rarely requires this type of
implementation. In most cases, the static initialization approach is sufficient.
Reference: MSDN
Acknowledgments
[Gamma95] Gamma, Helm, Johnson, and Vlissides. Design Patterns: Elements of Reusable
Object-Oriented Software. Addison-Wesley, 1995.
[Lea99] Lea, Doug. Concurrent Programming in Java, Second Edition. Addison-Wesley, 1999.
Singleton (PHP)
<?php
class Singleton
{
/**
* @var Singleton The reference to *Singleton* instance of this class
*/
private static $instance;
/**
* Returns the *Singleton* instance of this class.
*
* @return Singleton The *Singleton* instance.
*/
public static function getInstance()
{
if (null === static::$instance) {
static::$instance = new static();
}
return static::$instance;
}
/**
* Protected constructor to prevent creating a new instance of the
* *Singleton* via the `new` operator from outside of this class.
*/
protected function __construct()
{
}
/**
* Private clone method to prevent cloning of the instance of the
* *Singleton* instance.
*
* @return void
*/
https://riptutorial.com/ 107
private function __clone()
{
}
/**
* Private unserialize method to prevent unserializing of the *Singleton*
* instance.
*
* @return void
*/
private function __wakeup()
{
}
}
$obj = Singleton::getInstance();
var_dump($obj === Singleton::getInstance()); // bool(true)
$anotherObj = SingletonChild::getInstance();
var_dump($anotherObj === Singleton::getInstance()); // bool(false)
The use of a singleton should be considered carefully before use. There are usually better
alternatives.
The main problem with a singleton is the same as the problem with global variables. They
introduce external global mutable state. This means that functions that use a singleton are not
solely dependent on the input parameters but also the state of the singleton. This means that
testing can be severely compromised (difficult).
The issues with singletons can be mitigated by using them in conjunction with creation patterns; so
that the initial creation of the singleton can be controlled.
https://riptutorial.com/ 108
Chapter 28: SOLID
Introduction
What is S.O.L.I.D ?
S.O.L.I.D. is a mnemonic(memory aid) acronym. The Solid principles should help software
developers to avoid „code smells“ and should lead to good sourcecode. Good sourcecode means
in this context that the sourcecode is easy to extend and maintain. The main focus of the Solid
principles are classes
What to expect:
Examples
SRP - Single Responsibility Principle
Responsibility means in this context reasons to change, so the principle states that a class should
only have one reason to change.
Robert C. Martin stated it (during his lecture at Yale shool of management in 10 Sep 2014) as
follows
You could also say, don't put functions that change for different reasons in the same
class.
or
When you change a class you might affect functionality related to other responsibilities of the
class. Keeping the responsibilities at a low level minimizes the risk of side effects.
Bad example
We have an interface IWallet and a Wallet class which implements the IWallet. The Wallet holds
our money and the brand, furthermore should it print our money as string representation. The
class is used by
1. a webservice
https://riptutorial.com/ 109
2. a textwriter which prints the money in Euros into a textfile.
C# example code
https://riptutorial.com/ 110
public void setBrand(string brand)
{
m_Brand = brand;
}
Good example
https://riptutorial.com/ 111
To avoid the violation of the SRP, we removed the printMoney method from the Wallet class and
placed it into a Printer class. The Printer class is now responsible for the printing and the Wallet is
now responsible for the storing of the values.
C# example code
https://riptutorial.com/ 112
{
//print euro
}
}
https://riptutorial.com/ 113
Chapter 29: Static factory method
Examples
Static Factory method
We can provide several constructors with the same number and type of parameters, something
that as we saw earlier we can’t do with class constructors.
We can avoid providing direct access to resource intensive constructors, like for databases. public
class DbConnection { private static final int MAX_CONNS = 100; private static int totalConnections
= 0;
private DbConnection()
{
// ...
totalConnections++;
}
https://riptutorial.com/ 114
return new DbConnection();
}
else {
throw new NoDbConnections();
}
}
The static factory method is a variation of the factory method pattern. It is used to create objects
without having to call the constructor yourself.
• if you want to give a meaningfull name to the method that generates your object.
• if you want to avoid overcomplex object creation see Tuple Msdn.
• if you want to limit the number of objects created (caching)
• if you want to return an object of any subtype of their return type.
• Classes without a public or protected constructor cannot be initialized in the static factory
method.
• Static factory methods are like normal static methods, so they are not distinguishable from
other static methods (this may vary from IDE to IDE)
Example
Pizza.cs
private Pizza()
{
https://riptutorial.com/ 115
SizeDiameterCM = 25;
}
Program.cs
class Program
{
static void Main(string[] args)
{
var pizzaNormal = Pizza.GetPizza();
var pizzaLarge = Pizza.GetLargePizza();
var pizzaSmall = Pizza.GetSmallPizza();
Output
https://riptutorial.com/ 116
Chapter 30: Strategy Pattern
Examples
Hiding strategy implementation details
A very common guideline in object oriented design is "as little as possible but as much as
necessary". This also applies to the strategy pattern: It is usually advisable to hide implementation
details, for example which classes actually implement strategies.
For simple strategies which do not depend on external parameters, the most common approach is
to make the implementing class itself private (nested classes) or package-private and exposing an
instance through a static field of a public class:
// Note that this field has the generic type Comparator<Animal>, *not*
// Animal.AgeComparator!
public static final Comparator<Animal> AGE_COMPARATOR = new AgeComparator();
Animal(int age) {
this.age = age;
}
Collections.sort(
myList,
Animal.AGE_COMPARATOR
);
The public field Animal.AGE_COMPARATOR defines a strategy which can then be used in methods such
as Collections.sort, but it does not require the user to know anything about its implementation, not
even the implementing class.
https://riptutorial.com/ 117
If you prefer, you can use an anonymous class:
// other members...
}
If the strategy is a little more complex and requires parameters, it is very common to use static
factory methods such as Collections.reverseOrder(Comparator<T>). The return type of the method
should not expose any implementation details, e.g. reverseOrder() is implemented like
Strategy:
Strategy is a behavioural pattern, which allows to change the algorithm dynamically from a family
of related algorithms.
import java.util.*;
https://riptutorial.com/ 118
return 0;
}
}
/* Concrete implementation of base Strategy */
class QuarterDiscountStrategy implements OfferStrategy{
public String getName(){
return this.getClass().getName();
}
public double getDiscountPercentage(){
return 0.25;
}
}
/* Context is optional. But if it is present, it acts as single point of contact
for client.
}
}
public class StrategyDemo{
public static void main(String args[]){
StrategyContext context = new StrategyContext(100);
System.out.println("Enter month number between 1 and 12");
int month = Integer.parseInt(args[0]);
System.out.println("Month ="+month);
https://riptutorial.com/ 119
OfferStrategy strategy = context.getStrategy(month);
context.applyStrategy(strategy);
}
output:
Problem statement: Offer 25% discount on price of item for the months of July-December. Do not
provide any discount for the months of Jan-June.
Above example shows the usage of Strategy pattern with Context. Context can be used as Single
Point of Contact for the Client.
Two Strategies - NoOfferStrategy and QuarterDiscountStrategy have been declared as per problem
statement.
As shown in the output column, you will get discount depending on the month you have entered
1. Use this pattern when you have a family of interchangeable algorithms and you have to
change the algorithm at run time.
The following is a simple example of using the strategy pattern without a context class. There are
two implementation strategies which implement the interface and solve the same problem in
different ways. Users of the EnglishTranslation class can call the translate method and choose
which strategy they would like to use for the translation, by specifying the desired strategy.
@Override
public String translate(String phrase) {
https://riptutorial.com/ 120
return phrase + ", bro";
}
}
@Override
public String translate(String phrase) {
return phrase + ", mate";
}
}
// example usage
public static void main(String[] args) {
The purpose of this example is to show how we can realize the Strategy pattern using Java 8
functional interfaces. We will start with a simple use case codes in classic Java, and then recode it
in the Java 8 way.
The example problem we using is a family of algorithms (strategies) that describe different ways to
communicate over a distance.
https://riptutorial.com/ 121
public String communicate(String destination) {
return "communicating " + destination +" via Phone..";
}
}
// via phone
communicationService.setCommuncationMeans(communicateViaPhone);
communicationService.communicate("1234567");
// via email
communicationService.setCommuncationMeans(communicateViaEmail);
communicationService.communicate("hi@me.com");
https://riptutorial.com/ 122
The different algorithms composing the family of algorithms can be expressed as lambda
expressions. This replaces the strategy classes and their instantiations.
// via phone
communicationService.setCommuncationMeans(communicateViaPhone);
communicationService.communicate("1234567");
// via email
communicationService.setCommuncationMeans(communicateViaEmail);
communicationService.communicate("hi@me.com");
Or even:
communicationService.setCommuncationMeans(
destination -> "communicating " + destination + " via Smoke signals.." );
CommunicationService.communicate("anyone");
Strategy (PHP)
<?php
interface OutputInterface
{
public function load();
}
https://riptutorial.com/ 123
{
public function load()
{
return serialize($arrayOfData);
}
}
https://riptutorial.com/ 124
Chapter 31: Template Method
Examples
Template method implementation in java
Template method pattern is a behavioral design pattern that defines the program skeleton of an
algorithm in an operation, defering some steps to subclasses.
Structure:
Key notes:
Code example:
import java.util.List;
class GameRule{
}
class GameInfo{
String gameName;
List<String> players;
List<GameRule> rules;
}
https://riptutorial.com/ 125
public Game(GameInfo info){
this.info = info;
}
public abstract void createGame();
public abstract void makeMoves();
public abstract void applyRules();
}
class Ludo extends Game{
public Ludo(GameInfo info){
super(info);
}
public void createGame(){
// Use GameInfo and create Game
System.out.println("Creating Ludo game");
}
https://riptutorial.com/ 126
public void makeMoves(){
System.out.println("Make Ludo moves");
}
public void applyRules(){
System.out.println("Apply Ludo rules");
}
}
Explanation:
3. Sub-classes like Chess, Ludo and Checkers can't change the skeleton of playGame(). But they
can modify the behaviour of some steps like
createGame();
makeMoves();
applyRules();
output:
--------------------
Creating Chess game
Make Chess moves
Apply Chess rules
Close game:Chess
--------------------
Creating Ludo game
Make Ludo moves
Apply Ludo rules
Close game:Ludo
--------------------
Creating Checkers game
Make Checkers moves
Apply Checkers rules
Close game:Checkers
--------------------
https://riptutorial.com/ 127
Chapter 32: Visitor Pattern
Examples
Visitor Pattern example in C++
Instead of
struct IShape
{
virtual ~IShape() = default;
struct Point {
double x;
double y;
};
https://riptutorial.com/ 128
Point center;
double radius;
};
Point topLeft;
double sideLength;
};
double area = 0;
};
ShapePrinter shapePrinter;
ShapeAreaComputer shapeAreaComputer;
ShapePerimeterComputer shapePerimeterComputer;
https://riptutorial.com/ 129
shape->accept(shapePrinter);
std::cout << " has an area of ";
Expected output:
Demo
Explanation:
• For square.accept(visitor); call, the dynamic dispatch through virtual is used to know which
accept to call.
Pros:
• You may add new functionality (SerializeAsXml, ...) to the class IShape just by adding a new
visitor.
Cons:
• Adding a new concrete shape (Triangle, ...) requires to modifying all visitors.
The alternative of putting all functionalities as virtual methods in IShape has opposite pros and
cons: Adding new functionality requires to modify all existing shapes, but adding a new shape
doesn't impact existing classes.
Visitor pattern allows you to add new operations or methods to a set of classes without modifying
the structure of those classes.
This pattern is especially useful when you want to centralise a particular operation on an object
without extending the object Or without modifying the object.
https://riptutorial.com/ 130
UML diagram from wikipedia:
Code snippet:
import java.util.HashMap;
interface Visitable{
void accept(Visitor visitor);
}
interface Visitor{
void logGameStatistics(Chess chess);
void logGameStatistics(Checkers checkers);
void logGameStatistics(Ludo ludo);
}
class GameVisitor implements Visitor{
public void logGameStatistics(Chess chess){
System.out.println("Logging Chess statistics: Game Completion duration, number of
moves etc..");
}
public void logGameStatistics(Checkers checkers){
System.out.println("Logging Checkers statistics: Game Completion duration, remaining
coins of loser");
}
public void logGameStatistics(Ludo ludo){
System.out.println("Logging Ludo statistics: Game Completion duration, remaining coins
of loser");
}
}
}
public void getNextMove(){};
public void makeNextMove(){}
public abstract String getName();
}
class Chess extends Game implements Visitable{
public String getName(){
return Chess.class.getName();
}
https://riptutorial.com/ 131
public void accept(Visitor visitor){
visitor.logGameStatistics(this);
}
}
class Checkers extends Game implements Visitable{
public String getName(){
return Checkers.class.getName();
}
public void accept(Visitor visitor){
visitor.logGameStatistics(this);
}
}
class Ludo extends Game implements Visitable{
public String getName(){
return Ludo.class.getName();
}
public void accept(Visitor visitor){
visitor.logGameStatistics(this);
}
}
Explanation:
1. Visitable (Element) is an interface and this interface method has to be added to a set of
classes.
2. Visitor is an interface, which contains methods to perform an operation on Visitable
elements.
3. GameVisitor is a class, which implements Visitor interface ( ConcreteVisitor).
4. Each Visitable element accept Visitor and invoke a relevant method of Visitor interface.
5. You can treat Game as Element and concrete games like Chess,Checkers and Ludo as
ConcreteElements.
In above example, Chess, Checkers and Ludo are three different games ( and Visitable classes). On
one fine day, I have encountered with a scenario to log statistics of each game. So without
modifying individual class to implement statistics functionality, you can centralise that responsibility
in GameVisitor class, which does the trick for you without modifying the structure of each game.
output:
Use cases/Applicability:
https://riptutorial.com/ 132
1. Similar operations have to be performed on objects of different types grouped in a structure
2. You need to execute many distinct and unrelated operations. It separates Operation from
objects Structure
3. New operations have to be added without change in object structure
4. Gather related operations into a single class rather than force you to change or derive
classes
5. Add functions to class libraries for which you either do not have the source or cannot change
the source
Additional references:
oodesign
sourcemaking
class VehicleVisitor
{
public:
https://riptutorial.com/ 133
// The visitor interface implements one method for each class in the
// hierarchy. When implementing new functionality you just create the
// functionality required for each type in the appropriate method.
An example usage:
int main()
{
MoveVehicleVisitor moveToDenver("Denver");
Vehicle& object = getObjectToMove();
object.accept(moveToDenver);
}
class GraphVisitor;
class Graph
{
public:
class Node
{
using Link = std::set<Node>::iterator;
std::set<Link> linkTo;
public:
void accept(GraphVisitor& visitor);
};
private:
std::set<Node> nodes;
};
class GraphVisitor
https://riptutorial.com/ 134
{
std::set<Graph::Node*> visited;
public:
void visit(Graph& graph)
{
visited.clear();
doVisit(graph);
}
bool visit(Graph::Node& node)
{
if (visited.find(&node) != visited.end()) {
return false;
}
visited.insert(&node);
doVisit(node);
return true;
}
private:
virtual void doVisit(Graph& graph) = 0;
virtual void doVisit(Graph::Node& node) = 0;
};
https://riptutorial.com/ 135
Credits
S.
Chapters Contributors
No
Chain of
6 Ben Rhys-Lewis
Responsibility
Data Access
9 Object(DAO) design Pritam Banerjee
pattern
Dependency
11 Kritner, matiaslauriti, user2321864
Injection
17 Monostate skypjack
https://riptutorial.com/ 136
18 Multiton Kid Binary
27 SOLID Bongo
https://riptutorial.com/ 137