Computer Science Design Patterns
Abstract Factory
[edit | edit source]
The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes. In normal usage, the client software creates a concrete implementation of the abstract factory and then uses the generic interface of the factory to create the concrete objects that are part of the theme. The client does not know (or care) which concrete objects it gets from each of these internal factories, since it uses only the generic interfaces of their products. This pattern separates the details of implementation of a set of objects from their general usage and relies on object composition, as object creation is implemented in methods exposed in the factory interface. An example of this would be an abstract factory class DocumentCreator
that provides interfaces to create a number of products (e.g. createLetter()
and createResume()
). The system would have any number of derived concrete versions of the DocumentCreator
class like FancyDocumentCreator
or ModernDocumentCreator
, each with a different implementation of createLetter()
and createResume()
that would create a corresponding object like FancyLetter
or ModernResume
. Each of these products is derived from a simple abstract class like Letter
or Resume
of which the client is aware. The client code would get an appropriate instance of the DocumentCreator
and call its factory methods. Each of the resulting objects would be created from the same DocumentCreator
implementation and would share a common theme (they would all be fancy or modern objects). The client would only need to know how to handle the abstract Letter
or Resume
class, not the specific version that it got from the concrete factory.
A factory is the location of a concrete class in the code at which objects are constructed. The intent in employing the pattern is to insulate the creation of objects from their usage and to create families of related objects without having to depend on their concrete classes. This allows for new derived types to be introduced with no change to the code that uses the base class.
Use of this pattern makes it possible to interchange concrete implementations without changing the code that uses them, even at runtime. However, employment of this pattern, as with similar design patterns, may result in unnecessary complexity and extra work in the initial writing of code. Additionally, higher levels of separation and abstraction can result in systems which are more difficult to debug and maintain. Therefore, as in all software designs, the trade-offs must be carefully evaluated.
Definition
The essence of the Abstract Factory Pattern is to "Provide an interface for creating families of related or dependent objects without specifying their concrete classes".
Usage
The factory determines the actual concrete type of object to be created, and it is here that the object is actually created (in C++, for instance, by the new
operator). However, the factory only returns an abstract pointer to the created concrete object.
This insulates client code from object creation by having clients ask a factory object to create an object of the desired abstract type and to return an abstract pointer to the object.
As the factory only returns an abstract pointer, the client code (that requested the object from the factory) does not know — and is not burdened by — the actual concrete type of the object that was just created. However, the type of a concrete object (and hence a concrete factory) is known by the abstract factory; for instance, the factory may read it from a configuration file. The client has no need to specify the type, since it has already been specified in the configuration file. In particular, this means:
- The client code has no knowledge whatsoever of the concrete type, not needing to include any header files or class declarations related to it. The client code deals only with the abstract type. Objects of a concrete type are indeed created by the factory, but the client code accesses such objects only through their abstract interface.
- Adding new concrete types is done by modifying the client code to use a different factory, a modification that is typically one line in one file. The different factory then creates objects of a different concrete type, but still returns a pointer of the same abstract type as before — thus insulating the client code from change. This is significantly easier than modifying the client code to instantiate a new type, which would require changing every location in the code where a new object is created (as well as making sure that all such code locations also have knowledge of the new concrete type, by including for instance a concrete class header file). If all factory objects are stored globally in a singleton object, and all client code goes through the singleton to access the proper factory for object creation, then changing factories is as easy as changing the singleton object.
Structure
Class diagram
The method createButton
on the GuiFactory
interface returns objects of type Button
. What implementation of Button
is returned depends on which implementation of GuiFactory
is handling the method call.
Note that, for conciseness, this class diagram only shows the class relations for creating one type of object.
Lepus3 chart (legend)
UML diagram
Implementations
The output should be either "I'm a WinButton" or "I'm an OSXButton" depending on which kind of factory was used. Note that the Application has no idea what kind of GUIFactory it is given or even what kind of Button that factory creates.
/* GUIFactory example -- */
using System;
using System.Configuration;
namespace AbstractFactory {
public interface IButton {
void Paint();
}
public interface IGUIFactory {
IButton CreateButton();
}
public class OSXButton : IButton { // Executes fourth if OS:OSX
public void Paint() {
System.Console.WriteLine("I'm an OSXButton");
}
}
public class WinButton : IButton { // Executes fourth if OS:WIN
public void Paint() {
System.Console.WriteLine("I'm a WinButton");
}
}
public class OSXFactory : IGUIFactory { // Executes third if OS:OSX
IButton IGUIFactory.CreateButton() {
return new OSXButton();
}
}
public class WinFactory : IGUIFactory { // Executes third if OS:WIN
IButton IGUIFactory.CreateButton() {
return new WinButton();
}
}
public class Application {
public Application(IGUIFactory factory) {
IButton button = factory.CreateButton();
button.Paint();
}
}
public class ApplicationRunner {
static IGUIFactory CreateOsSpecificFactory() { // Executes second
// Contents of App.Config associated with this C# project
//<?xml version="1.0" encoding="utf-8" ?>
//<configuration>
// <appSettings>
// <!-- Uncomment either Win or OSX OS_TYPE to test -->
// <add key="OS_TYPE" value="Win" />
// <!-- <add key="OS_TYPE" value="OSX" /> -->
// </appSettings>
//</configuration>
string sysType = ConfigurationSettings.AppSettings["OS_TYPE"];
if (sysType == "Win") {
return new WinFactory();
} else {
return new OSXFactory();
}
}
static void Main() { // Executes first
new Application(CreateOsSpecificFactory());
Console.ReadLine();
}
}
}
/* GUIFactory example */
#include <iostream>
class Button {
public:
virtual void paint() = 0;
virtual ~Button() { }
};
class WinButton : public Button {
public:
void paint() {
std::cout << "I'm a WinButton";
}
};
class OSXButton : public Button {
public:
void paint() {
std::cout << "I'm an OSXButton";
}
};
class GUIFactory {
public:
virtual Button* createButton() = 0;
virtual ~GUIFactory() { }
};
class WinFactory : public GUIFactory {
public:
Button* createButton() {
return new WinButton();
}
~WinFactory() { }
};
class OSXFactory : public GUIFactory {
public:
Button* createButton() {
return new OSXButton();
}
~OSXFactory() { }
};
class Application {
public:
Application(GUIFactory* factory) {
Button* button = factory->createButton();
button->paint();
delete button;
delete factory;
}
};
GUIFactory* createOsSpecificFactory() {
int sys;
std::cout << "Enter OS type (0: Windows, 1: MacOS X): ";
std::cin >> sys;
if (sys == 0) {
return new WinFactory();
} else {
return new OSXFactory();
}
}
int main() {
Application application(createOsSpecificFactory());
return 0;
}
/* GUIFactory example -- */
interface Button {
void paint();
}
interface GUIFactory {
Button createButton();
}
class WinFactory implements GUIFactory {
public Button createButton() {
return new WinButton();
}
}
class OSXFactory implements GUIFactory {
public Button createButton() {
return new OSXButton();
}
}
class WinButton implements Button {
public void paint() {
System.out.println("I'm a WinButton");
}
}
class OSXButton implements Button {
public void paint() {
System.out.println("I'm an OSXButton");
}
}
class Application {
public Application(GUIFactory factory) {
Button button = factory.createButton();
button.paint();
}
}
public class ApplicationRunner {
public static void main(String[] args) {
new Application(createOsSpecificFactory());
}
public static GUIFactory createOsSpecificFactory() {
int sys = readFromConfigFile("OS_TYPE");
if (sys == 0) return new WinFactory();
else return new OSXFactory();
}
}
/* GUIFactory example -- */
#import <Foundation/Foundation.h>
@protocol Button <NSObject>
- (void)paint;
@end
@interface WinButton : NSObject <Button>
@end
@interface OSXButton : NSObject <Button>
@end
@protocol GUIFactory
- (id<Button>)createButton;
@end
@interface WinFactory : NSObject <GUIFactory>
@end
@interface OSXFactory : NSObject <GUIFactory>
@end
@interface Application : NSObject
- (id)initWithGUIFactory:(id)factory;
+ (id)createOsSpecificFactory:(int)type;
@end
@implementation WinButton
- (void)paint {
NSLog(@"I am a WinButton.");
}
@end
@implementation OSXButton
- (void)paint {
NSLog(@"I am a OSXButton.");
}
@end
@implementation WinFactory
- (id<Button>)createButton {
return [[[WinButton alloc] init] autorelease];
}
@end
@implementation OSXFactory
- (id<Button>)createButton {
return [[[OSXButton alloc] init] autorelease];
}
@end
@implementation Application
- (id)initWithGUIFactory:(id<GUIFactory>)factory {
if (self = [super init]) {
id button = [factory createButton];
[button paint];
}
return self;
}
+ (id<GUIFactory>)createOsSpecificFactory:(int)type {
if (type == 0) {
return [[[WinFactory alloc] init] autorelease];
} else {
return [[[OSXFactory alloc] init] autorelease];
}
}
@end
int main(int argc, char* argv[]) {
@autoreleasepool {
[[Application alloc] initWithGUIFactory:[Application createOsSpecificFactory:0]];// 0 is WinButton
}
return 0;
}
--[[
Because Lua is a highly dynamic Language, an OOP scheme is implemented by the programmer.
The OOP scheme implemented here implements interfaces using documentation.
A Factory Supports:
- factory:CreateButton()
A Button Supports:
- button:Paint()
]]
-- Create the OSXButton Class
do
OSXButton = {}
local mt = { __index = OSXButton }
function OSXButton:new()
local inst = {}
setmetatable(inst, mt)
return inst
end
function OSXButton:Paint()
print("I'm a fancy OSX button!")
end
end
-- Create the WinButton Class
do
WinButton = {}
local mt = { __index = WinButton }
function WinButton:new()
local inst = {}
setmetatable(inst, mt)
return inst
end
function WinButton:Paint()
print("I'm a fancy Windows button!")
end
end
-- Create the OSXGuiFactory Class
do
OSXGuiFactory = {}
local mt = { __index = OSXGuiFactory }
function OSXGuiFactory:new()
local inst = {}
setmetatable(inst, mt)
return inst
end
function OSXGuiFactory:CreateButton()
return OSXButton:new()
end
end
-- Create the WinGuiFactory Class
do
WinGuiFactory = {}
local mt = { __index = WinGuiFactory }
function WinGuiFactory:new()
local inst = {}
setmetatable(inst, mt)
return inst
end
function WinGuiFactory:CreateButton()
return WinButton:new()
end
end
-- Table to keep track of what GuiFactories are available
GuiFactories = {
["Win"] = WinGuiFactory,
["OSX"] = OSXGuiFactory,
}
--[[ Inside an OS config script ]]
OS_VERSION = "Win"
--[[ Using the Abstract Factory in some the application script ]]
-- Selecting the factory based on OS version
MyGuiFactory = GuiFactories[OS_VERSION]:new()
-- Using the factory
osButton = MyGuiFactory:CreateButton()
osButton:Paint()
This abstract factory creates books.
/*
* BookFactory classes
*/
abstract class AbstractBookFactory {
abstract function makePHPBook();
abstract function makeMySQLBook();
}
class OReillyBookFactory extends AbstractBookFactory {
private $context = "OReilly";
function makePHPBook() {
return new OReillyPHPBook;
}
function makeMySQLBook() {
return new OReillyMySQLBook;
}
}
class SamsBookFactory extends AbstractBookFactory {
private $context = "Sams";
function makePHPBook() {
return new SamsPHPBook;
}
function makeMySQLBook() {
return new SamsMySQLBook;
}
}
/*
* Book classes
*/
abstract class AbstractBook {
abstract function getAuthor();
abstract function getTitle();
}
abstract class AbstractMySQLBook extends AbstractBook {
private $subject = "MySQL";
}
class OReillyMySQLBook extends AbstractMySQLBook {
private $author;
private $title;
function __construct() {
$this->author = 'George Reese, Randy Jay Yarger, and Tim King';
$this->title = 'Managing and Using MySQL';
}
function getAuthor() {
return $this->author;
}
function getTitle() {
return $this->title;
}
}
class SamsMySQLBook extends AbstractMySQLBook {
private $author;
private $title;
function __construct() {
$this->author = 'Paul Dubois';
$this->title = 'MySQL, 3rd Edition';
}
function getAuthor() {
return $this->author;
}
function getTitle() {
return $this->title;
}
}
abstract class AbstractPHPBook extends AbstractBook {
private $subject = "PHP";
}
class OReillyPHPBook extends AbstractPHPBook {
private $author;
private $title;
private static $oddOrEven = 'odd';
function __construct() {
//alternate between 2 books
if ('odd' == self::$oddOrEven) {
$this->author = 'Rasmus Lerdorf and Kevin Tatroe';
$this->title = 'Programming PHP';
self::$oddOrEven = 'even';
} else {
$this->author = 'David Sklar and Adam Trachtenberg';
$this->title = 'PHP Cookbook';
self::$oddOrEven = 'odd';
}
}
function getAuthor() {
return $this->author;
}
function getTitle() {
return $this->title;
}
}
class SamsPHPBook extends AbstractPHPBook {
private $author;
private $title;
function __construct() {
//alternate randomly between 2 books
mt_srand((double)microtime() * 10000000);
$rand_num = mt_rand(0, 1);
if (1 > $rand_num) {
$this->author = 'George Schlossnagle';
$this->title = 'Advanced PHP Programming';
}
else {
$this->author = 'Christian Wenz';
$this->title = 'PHP Phrasebook';
}
}
function getAuthor() {
return $this->author;
}
function getTitle() {
return $this->title;
}
}
/*
* Initialization
*/
writeln('BEGIN TESTING ABSTRACT FACTORY PATTERN');
writeln('');
writeln('testing OReillyBookFactory');
$bookFactoryInstance = new OReillyBookFactory;
testConcreteFactory($bookFactoryInstance);
writeln('');
writeln('testing SamsBookFactory');
$bookFactoryInstance = new SamsBookFactory;
testConcreteFactory($bookFactoryInstance);
writeln("END TESTING ABSTRACT FACTORY PATTERN");
writeln('');
function testConcreteFactory($bookFactoryInstance) {
$phpBookOne = $bookFactoryInstance->makePHPBook();
writeln('first php Author: '.$phpBookOne->getAuthor());
writeln('first php Title: '.$phpBookOne->getTitle());
$phpBookTwo = $bookFactoryInstance->makePHPBook();
writeln('second php Author: '.$phpBookTwo->getAuthor());
writeln('second php Title: '.$phpBookTwo->getTitle());
$mySqlBook = $bookFactoryInstance->makeMySQLBook();
writeln('MySQL Author: '.$mySqlBook->getAuthor());
writeln('MySQL Title: '.$mySqlBook->getTitle());
}
function writeln($line_in) {
echo $line_in."<br/>";
}
This abstract factory creates musicians.
// concrete implementation
class DrummerFactory extends MusicianAbstractFactory {
def create(): Musician = new Drummer()
}
class GuitarPlayerFactory extends MusicianAbstractFactory {
def create(): Musician = new GuitarPlayer()
}
class GuitarPlayer extends Musician {
def play(song: String) {
println(s"I'm guitar player and I play $song")
}
}
class Drummer extends Musician {
def play(song: String) {
println(s"I'm drummer and I play '$song'")
}
}
object FactoryCreator {
def getFactory(config: Boolean): MusicianAbstractFactory =
if (config) {
new DrummerFactory
} else {
new GuitarPlayerFactory
}
}
// interfaces to import
trait Musician {
def play(song: String)
}
trait MusicianAbstractFactory {
def create(): Musician
}
import implementation.FactoryCreator
object AbstractFactoryTest {
def readFromConfig(): Boolean = true
def main(args: Array[String]) {
val factory = FactoryCreator.getFactory(readFromConfig())
val musician = factory.create()
musician.play("Highway to hell")
}
}
from abc import ABC, abstractmethod
from sys import platform
class Button(ABC):
@abstractmethod
def paint(self):
pass
class LinuxButton(Button):
def paint(self):
return "Render a button in a Linux style"
class WindowsButton(Button):
def paint(self):
return "Render a button in a Windows style"
class MacOSButton(Button):
def paint(self):
return "Render a button in a MacOS style"
class GUIFactory(ABC):
@abstractmethod
def create_button(self):
pass
class LinuxFactory(GUIFactory):
def create_button(self):
return LinuxButton()
class WindowsFactory(GUIFactory):
def create_button(self):
return WindowsButton()
class MacOSFactory(GUIFactory):
def create_button(self):
return MacOSButton()
if platform == "linux":
factory = LinuxFactory()
elif platform == "darwin":
factory = MacOSFactory()
elif platform == "win32":
factory = WindowsFactory()
else:
raise NotImplementedError(f"Not implemented for your platform: {platform}")
button = factory.create_button()
result = button.paint()
print(result)
Alternative implementation using the classes themselves as factories:
from abc import ABC, abstractmethod
from sys import platform
class Button(ABC):
@abstractmethod
def paint(self):
pass
class LinuxButton(Button):
def paint(self):
return "Render a button in a Linux style"
class WindowsButton(Button):
def paint(self):
return "Render a button in a Windows style"
class MacOSButton(Button):
def paint(self):
return "Render a button in a MacOS style"
if platform == "linux":
factory = LinuxButton
elif platform == "darwin":
factory = MacOSButton
elif platform == "win32":
factory = WindowsButton
else:
raise NotImplementedError(f"Not implemented for your platform: {platform}")
button = factory()
result = button.paint()
print(result)
Another example:
import platform
class GuiFactory():
"""Abstract Factory"""
@classmethod
def getFactory(Class):
if platform.system() == "Windows":
return WinFactory()
elif platform.system() == "OSX":
return OSXFactory()
elif platform.system() == "Linux":
return LinuxFactory()
class Button:
""" Abstract Product"""
def paint(self):
raise NotImplementedError
@classmethod
def getButton(Class):
return Class.Button()
class WinFactory(GuiFactory):
"""Concrete Factory"""
class Button(GuiFactory.Button):
"""Concrete Product"""
def paint(self):
print "I am a Windows button"
class LinuxFactory(GuiFactory):
"""Concrete Factory"""
class Button(GuiFactory.Button):
"""Concrete Product"""
def paint(self):
print "I am a Linux button"
class OSXFactory(GuiFactory):
"""Concrete Factory"""
class Button(GuiFactory.Button):
"""Concrete Product"""
def paint(self):
print "I am a OSX button"
def main():
"""Application"""
factory = GuiFactory.getFactory()
factory.getButton().paint()
if __name__ == "__main__":
main()
program AbstractFactory;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
(* abstract factory *)
TAbstractFactory = class abstract
procedure Paint(); virtual; abstract;
end;
(* abstract product *)
TGUIFactory = class abstract
function CreateButton(): TAbstractFactory; virtual; abstract;
end;
(* concrete product *)
TOSXButton = class(TAbstractFactory)
public
procedure Paint(); override;
end;
(* concrete product *)
TWinButton = class(TAbstractFactory)
public
procedure Paint(); override;
end;
(* concrete factory *)
TOSXFactory = class(TGUIFactory)
public
function CreateButton(): TAbstractFactory; override;
end;
(* concrete factory *)
TWinFactory = class(TGUIFactory)
public
function CreateButton(): TAbstractFactory; override;
end;
(* client *)
TApplication = class
public
constructor Create(factory: TGUIFactory);
end;
(* Just for OOP style use class. This function is to return button factory only. *)
TApplicationRunner = class
public
class function CreateOsSpecificFactory: TGUIFactory;
end;
{ TOSXButton }
procedure TOSXButton.Paint;
begin
WriteLn('I`m an OSXButton');
end;
{ TWinButton }
procedure TWinButton.Paint;
begin
WriteLn('I`m a WinButton');
end;
{ TOSXFactory }
function TOSXFactory.CreateButton: TAbstractFactory;
begin
Result := TOSXButton.Create;
end;
{ TWinFactory }
function TWinFactory.CreateButton: TAbstractFactory;
begin
Result := TWinButton.Create;
end;
{ TApplication }
constructor TApplication.Create(factory: TGUIFactory);
var
button: TAbstractFactory;
begin
button := factory.CreateButton;
button.Paint;
end;
{ TApplicationRunner }
class function TApplicationRunner.CreateOsSpecificFactory: TGUIFactory;
var
sysType: string;
begin
WriteLn('Enter OS type (Win: Windows, OSX: MacOS X)');
ReadLn(sysType);
if (sysType = 'Win') then
Result := TWinFactory.Create
else
Result := TOSXFactory.Create
end;
var
App: TApplication;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
App := TApplication.Create(TApplicationRunner.CreateOsSpecificFactory);
WriteLn(#13#10 + 'Press any key to continue...');
ReadLn;
App.Free;
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
end.
Adapter
[edit | edit source]
The adapter pattern is used when a client class has to call an incompatible provider class. Let's imagine a MailingClient class that needs to call a method on the LegacyEmployee class:
|
|
|
MailingClient
already calls classes that implement the IEmployee
interface but the LegacyEmployee
doesn't implement it. We could add a new method to LegacyEmployee
to implement the IEmployee
interface but LegacyEmployee
is legacy code and can't be changed. We could modify the MailingClient
class to call LegacyEmployee
but it needs to change every call. The formatting code would be duplicated everywhere. Moreover, MailingClient
won't be able to call other provider class that implement the IEmployee
interface any more.
So the solution is to code the formatting code in another independent class, an adapter, also called a wrapper class:
|
|||||||||||||
|
|
|
EmployeeAdapter
implements the IEmployee
interface. MailingClient
calls EmployeeAdapter
. EmployeeAdapter
formats the data and calls LegacyEmployee
. This type of adapter is called an object adapter. The other type of adapter is the class adapter.
Examples
The WebGL-2D is a JavaScript library that implements the adapter pattern. This library is used for the HTML5 canvas element. The canvas element has two interfaces: 2d and WebGL. The first one is very simple to use and the second is much more complex but optimized and faster. The WebGL-2D 'adapts' the WebGL interface to the 2d interface, so that the client calls the 2d interface only.
Cost
Think twice before implementing this pattern. This pattern should not be planned at design time. If you plan to use it for a project from scratch, this means that you don't understand this pattern. It should be used only with legacy code. It is the least bad solution.
Creation
Its implementation is easy but can be expensive. You should not have to refactor the code as the client and the provider should not be able to work together yet.
Maintenance
This is the worst part. Most of the code has redundancies (but less than without the pattern). The modern interface should always provide as much information as the legacy interface needs to work. If one information is missing on the modern interface, it can call the pattern into question.
Removal
This pattern can be easily removed as automatic refactoring operations can easily remove its existence.
Advices
- Put the adapter term in the name of the adapter class to indicate the use of the pattern to the other developers.
Implementation
Object Adapter
Our company has been created by a merger. One list of employees is available in a database you can access via the CompanyAEmployees
class:
/**
* Employees of the Company A.
*/
public class CompanyAEmployees {
/**
* Retrieve the employee information from the database.
*
* @param sqlQuery The SQL query.
* @return The employee object.
*/
public Employee getEmployee(String sqlQuery) {
Employee employee = null;
// Execute the request.
return employee;
}
}
One list of employees is available in a LDAP you can access via the CompanyBEmployees
class:
/**
* Employees of the Company B.
*/
public class CompanyBEmployees {
/**
* Retrieve the employee information from the LDAP.
*
* @param sqlQuery The SQL query.
* @return The employee object.
*/
public Employee getEmployee(String distinguishedName) {
Employee employee = null;
// Call the LDAP.
return employee;
}
}
To access both to the former employees of the company A and the former employees of the company B, we define an interface that will be used by two adapters, EmployeeBrowser
:
/**
* Retrieve information about the employees.
*/
interface EmployeeBrowser {
/**
* Retrieve the employee information.
*
* @param direction The employee direction.
* @param division The employee division.
* @param department The employee departement.
* @param service The employee service.
* @param firstName The employee firstName.
* @param lastName The employee lastName.
*
* @return The employee object.
*/
Employee getEmployee(String direction, String division, String department, String service, String firstName, String lastName);
}
We create an adapter for the code of the former company A, CompanyAAdapter
:
/**
* Adapter for the company A legacy code.
*/
public class CompanyAAdapter implements EmployeeBrowser {
/**
* Retrieve the employee information.
*
* @param direction The employee direction.
* @param division The employee division.
* @param department The employee department.
* @param service The employee service.
* @param firstName The employee firstName.
* @param lastName The employee lastName.
*
* @return The employee object.
*/
public Employee getEmployee(String direction, String division, String department, String service, String firstName, String lastName) {
String distinguishedName = "SELECT *"
+ " FROM t_employee as employee"
+ " WHERE employee.company= 'COMPANY A'"
+ " AND employee.direction = " + direction
+ " AND employee.division = " + division
+ " AND employee.department = " + department
+ " AND employee.service = " + service
+ " AND employee.firstName = " + firstName
+ " AND employee.lastName = " + lastName;
CompanyAEmployees companyAEmployees = new CompanyAEmployees();
return companyAEmployees.getEmployee(distinguishedName);
}
}
We create an adapter for the code of the former company B, CompanyBAdapter
:
/**
* Adapter for the company B legacy code.
*/
public class CompanyBAdapter implements EmployeeBrowser {
/**
* Retrieve the employee information.
*
* @param direction The employee direction.
* @param division The employee division.
* @param department The employee department.
* @param service The employee service.
* @param firstName The employee firstName.
* @param lastName The employee lastName.
*
* @return The employee object.
*/
public Employee getEmployee(String direction, String division, String department, String service, String firstName, String lastName) {
String distinguishedName = "ov1 = " + direction
+ ", ov2 = " + division
+ ", ov3 = " + department
+ ", ov4 = " + service
+ ", cn = " + firstName + lastName;
CompanyBEmployees companyBEmployees = new CompanyBEmployees();
return companyBEmployees.getEmployee(distinguishedName);
}
}
Ruby
class Adaptee
def specific_request
# do something
end
end
class Adapter
def initialize(adaptee)
@adaptee = adaptee
end
def request
@adaptee.specific_request
end
end
client = Adapter.new(Adaptee.new)
client.request
class Adaptee:
def specific_request(self):
return 'Adaptee'
class Adapter:
def __init__(self, adaptee):
self.adaptee = adaptee
def request(self):
return self.adaptee.specific_request()
client = Adapter(Adaptee())
print client.request()
trait Socket220V {
def plug220()
}
trait Socket19V {
def plug19()
}
class Laptop extends Socket19V {
def plug19() {
println("Charging....")
}
}
class LaptopAdapter(laptop: Laptop) extends Socket220V {
def plug220() {
println("Transform1...")
laptop.plug19()
}
}
object Test {
def main(args: Array[String]) {
//you can do it like this:
new LaptopAdapter(new Laptop).plug220()
//or like this (doesn't need LaptopAdapter)
new Laptop with Socket220V {
def plug220() {
println("Transform2...")
this.plug19()
}
} plug220()
}
}
program Adapter;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
(* Its interface *)
TTarget = class abstract
function Request: string; virtual; abstract;
end;
(* A client accessed to this. *)
TAdaptee = class(TTarget)
function Request: string; override;
end;
(* Object Adapter uses composition and can wrap classes or interfaces, or both.*)
(* Redirect call to Adaptee. It is loose coupling of client and adapter.*)
(*
*It can do this since it contains, as a private, encapsulated member,
*the class or interface object instance it wraps.
*)
TObjectAdapter = class
fAdaptee: TAdaptee;
function SpecialRequest: string;
constructor Create(adaptee: TAdaptee);
end;
{ TObjectAdapter }
constructor TObjectAdapter.Create;
begin
fAdaptee := TAdaptee.Create;
end;
function TObjectAdapter.SpecialRequest: string;
begin
Result := fAdaptee.Request;
end;
{ TAdaptee }
function TAdaptee.Request: string;
begin
Result := 'Adaptee';
end;
var
clientObject: TObjectAdapter;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
clientObject := TObjectAdapter.Create(TAdaptee.Create);
WriteLn('Call method Object Adapter: '+clientObject.SpecialRequest);
WriteLn(#13#10+ 'Press any key to continue...');
ReadLn;
clientObject.Free;
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
end.
Class Adapter
class Adaptee1:
def __init__(self, *args, **kw):
pass
def specific_request(self):
return 'Adaptee1'
class Adaptee2:
def __init__(self, *args, **kw):
pass
def specific_request(self):
return 'Adaptee2'
class Adapter(Adaptee1, Adaptee2):
def __init__(self, *args, **kw):
Adaptee1.__init__(self, *args, **kw)
Adaptee2.__init__(self, *args, **kw)
def request(self):
return Adaptee1.specific_request(self), Adaptee2.specific_request(self)
client = Adapter()
print client.request()
program Adapter;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
(* Its interface *)
TTarget = class abstract
function Request: string; virtual; abstract;
end;
(* A client accessed to this. *)
TAdaptee = class(TTarget)
function Request: string; override;
end;
(* Class Adapter uses inheritance and can only wrap a class.*)
(* This plain old inheritance. *)
(* It cannot wrap an interface since by definition*)
(* it must derive from some base class as Adaptee in example*)
(*
* Can't reuse Class Adapter without rewrite code
* You need implements other adapter with other method in other class.
*)
TClassAdapter = class(TAdaptee)
function SpecialRequest: string;
end;
{ TClassAdapter }
function TClassAdapter.SpecialRequest: string;
begin
//use inherited Request as SpecialRequest
Result:= inherited Request;
end;
{ TAdaptee }
function TAdaptee.Request: string;
begin
Result := 'Adaptee';
end;
var
clientClass:TClassAdapter;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
clientClass:= TClassAdapter.Create;
WriteLn('Call method Class Adapter: '+clientClass.SpecialRequest);
WriteLn(#13#10+ 'Press any key to continue...');
ReadLn;
clientClass.Free;
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
end.
Bridge
[edit | edit source]
Bridge pattern is useful when a code often changes for an implementation as well as for a use of code. In your application, you should have provider classes and client classes:
|
|
... |
|
◊— |
| |||||||||||||||||
... | ||||||||||||||||||||||
|
|
... |
|
Each client class can interact with each provider class. However, if the implementation changes, the method signatures of the Provider interface may change and all the client classes have to change. In the same way, if the client classes need a new interface, we need to rewrite all the providers. The solution is to add a bridge, that is to say a class that will be called by the clients, that contains a reference to the providers and forward the client call to the providers.
|
|
... |
|
◊— |
|
◊— |
| ||||||||||||||||||||
... | |||||||||||||||||||||||||||
|
|
... |
|
In the future, the two interfaces (client/bridge and bridge/provider) may change independently and the bridge may trans-code the call order.
Examples
It's hard to find an example in a library as this pattern is designed for versatile specifications and a library does not change constantly between two versions.
Cost
The cost of this pattern is the same as the adapter. It can be planned at design time but the best way to decide to add it is the experience feedback. Implement it when you have frequently changed an interface in a short time.
Creation
Its implementation is easy but can be expensive. It depends on the complexity of the interface. The more methods you have, the more expensive it will be.
Maintenance
If you always update the client/bridge interface and the bridge/provider interface the same way, it would be more expensive than if you do not implement the design pattern.
Removal
This pattern can be easily removed as automatic refactoring operations can easily remove its existence.
Advices
- Put the bridge term in the name of the bridge class to indicate the use of the pattern to the other developers.
Implementation
/** "Implementor" */
fun interface MusicPlayer {
fun play(song: String): String
}
/** "ConcreteImplementor" 1/4 */
val defaultPlayer = MusicPlayer{
"Reproducing $it in ${MusicFormat.NONE}"
}
/** "ConcreteImplementor" 2/4 */
val mp3Player = MusicPlayer{
"Reproducing $it in ${MusicFormat.MP3}"
}
/** "ConcreteImplementor" 3/4 */
val mp4Player = MusicPlayer{
"Reproducing $it in ${MusicFormat.MP4}"
}
/** "ConcreteImplementor" 4/4 */
val vlcPlayer = MusicPlayer{
"Reproducing \"$it\" in ${MusicFormat.VLC}"
}
/** "Abstraction" */
abstract class MusicPlayerUI {
var musicPlayer : MusicPlayer = defaultPlayer
abstract fun playMusic(song: String, musicFormat: MusicFormat)
}
/** "Refined Abstraction" */
class MyMusicPlayerUI : MusicPlayerUI() {
override fun playMusic(song: String, musicFormat: MusicFormat) {
musicPlayer = when(musicFormat) {
MusicFormat.NONE -> defaultPlayer
MusicFormat.MP3 -> mp3Player
MusicFormat.MP4 -> mp4Player
MusicFormat.VLC -> vlcPlayer
}
println(musicPlayer.play(song))
}
}
enum class MusicFormat{
NONE,MP3,MP4,VLC
}
/** "Client" */
object BridgePattern {
@JvmStatic
fun main(args: Array<String>) {
val musicPlayer = MyMusicPlayerUI()
musicPlayer.playMusic("The best song", MusicFormat.MP4)
}
}
The following Java (SE 6) program illustrates the bridge pattern.
/**
* Implementor
*/
interface DrawingAPI {
public void drawCircle(double x, double y, double radius);
}
/**
* ConcreteImplementor 1/2
*/
class DrawingAPI1 implements DrawingAPI {
public void drawCircle(double x, double y, double radius) {
System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
}
}
/**
* ConcreteImplementor 2/2
*/
class DrawingAPI2 implements DrawingAPI {
public void drawCircle(double x, double y, double radius) {
System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
}
}
/**
* Abstraction
*/
abstract class Shape {
protected DrawingAPI drawingAPI;
protected Shape(DrawingAPI drawingAPI) {
this.drawingAPI = drawingAPI;
}
public abstract void draw(); // low-level
public abstract void resizeByPercentage(double pct); // high-level
}
/**
* Refined Abstraction
*/
class CircleShape extends Shape {
private double x, y, radius;
public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
super(drawingAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
// low-level i.e. Implementation specific
public void draw() {
drawingAPI.drawCircle(x, y, radius);
}
// high-level i.e. Abstraction specific
public void resizeByPercentage(double pct) {
radius *= pct;
}
}
/**
* Client
*/
class BridgePattern {
public static void main(String[] args) {
Shape[] shapes = new Shape[] {
new CircleShape(1, 2, 3, new DrawingAPI1()),
new CircleShape(5, 7, 11, new DrawingAPI2()),
};
for (Shape shape : shapes) {
shape.resizeByPercentage(2.5);
shape.draw();
}
}
}
It will output:
API1.circle at 1.000000:2.000000 radius 7.5000000 API2.circle at 5.000000:7.000000 radius 27.500000
interface DrawingAPI {
function drawCircle($dX, $dY, $dRadius);
}
class DrawingAPI1 implements DrawingAPI {
public function drawCircle($dX, $dY, $dRadius) {
echo "API1.circle at ".$dX.":".$dY." radius ".$dRadius."<br/>";
}
}
class DrawingAPI2 implements DrawingAPI {
public function drawCircle($dX, $dY, $dRadius) {
echo "API2.circle at ".$dX.":".$dY." radius ".$dRadius."<br/>";
}
}
abstract class Shape {
protected $oDrawingAPI;
public abstract function draw();
public abstract function resizeByPercentage($dPct);
protected function __construct(DrawingAPI $oDrawingAPI) {
$this->oDrawingAPI = $oDrawingAPI;
}
}
class CircleShape extends Shape {
private $dX;
private $dY;
private $dRadius;
public function __construct(
$dX, $dY,
$dRadius,
DrawingAPI $oDrawingAPI
) {
parent::__construct($oDrawingAPI);
$this->dX = $dX;
$this->dY = $dY;
$this->dRadius = $dRadius;
}
public function draw() {
$this->oDrawingAPI->drawCircle(
$this->dX,
$this->dY,
$this->dRadius
);
}
public function resizeByPercentage($dPct) {
$this->dRadius *= $dPct;
}
}
class Tester {
public static function main() {
$aShapes = array(
new CircleShape(1, 3, 7, new DrawingAPI1()),
new CircleShape(5, 7, 11, new DrawingAPI2()),
);
foreach ($aShapes as $shapes) {
$shapes->resizeByPercentage(2.5);
$shapes->draw();
}
}
}
Tester::main();
Output:
API1.circle at 1:3 radius 17.5 API2.circle at 5:7 radius 27.5
C#
The following C# program illustrates the "shape" example given above and will output:
API1.circle at 1:2 radius 7.5 API2.circle at 5:7 radius 27.5
using System;
/** "Implementor" */
interface IDrawingAPI {
void DrawCircle(double x, double y, double radius);
}
/** "ConcreteImplementor" 1/2 */
class DrawingAPI1 : IDrawingAPI {
public void DrawCircle(double x, double y, double radius)
{
System.Console.WriteLine("API1.circle at {0}:{1} radius {2}", x, y, radius);
}
}
/** "ConcreteImplementor" 2/2 */
class DrawingAPI2 : IDrawingAPI
{
public void DrawCircle(double x, double y, double radius)
{
System.Console.WriteLine("API2.circle at {0}:{1} radius {2}", x, y, radius);
}
}
/** "Abstraction" */
interface IShape {
void Draw(); // low-level (i.e. Implementation-specific)
void ResizeByPercentage(double pct); // high-level (i.e. Abstraction-specific)
}
/** "Refined Abstraction" */
class CircleShape : IShape {
private double x, y, radius;
private IDrawingAPI drawingAPI;
public CircleShape(double x, double y, double radius, IDrawingAPI drawingAPI)
{
this.x = x; this.y = y; this.radius = radius;
this.drawingAPI = drawingAPI;
}
// low-level (i.e. Implementation-specific)
public void Draw() { drawingAPI.DrawCircle(x, y, radius); }
// high-level (i.e. Abstraction-specific)
public void ResizeByPercentage(double pct) { radius *= pct; }
}
/** "Client" */
class BridgePattern {
public static void Main(string[] args) {
IShape[] shapes = new IShape[2];
shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1());
shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2());
foreach (IShape shape in shapes) {
shape.ResizeByPercentage(2.5);
shape.Draw();
}
}
}
C# using generics
The following C# program illustrates the "shape" example given above and will output:
API1.circle at 1:2 radius 7.5 API2.circle at 5:7 radius 27.5
using System;
/** "Implementor" */
interface IDrawingAPI {
void DrawCircle(double x, double y, double radius);
}
/** "ConcreteImplementor" 1/2 */
struct DrawingAPI1 : IDrawingAPI {
public void DrawCircle(double x, double y, double radius)
{
System.Console.WriteLine("API1.circle at {0}:{1} radius {2}", x, y, radius);
}
}
/** "ConcreteImplementor" 2/2 */
struct DrawingAPI2 : IDrawingAPI
{
public void DrawCircle(double x, double y, double radius)
{
System.Console.WriteLine("API2.circle at {0}:{1} radius {2}", x, y, radius);
}
}
/** "Abstraction" */
interface IShape {
void Draw(); // low-level (i.e. Implementation-specific)
void ResizeByPercentage(double pct); // high-level (i.e. Abstraction-specific)
}
/** "Refined Abstraction" */
class CircleShape<T> : IShape
where T : struct, IDrawingAPI
{
private double x, y, radius;
private IDrawingAPI drawingAPI = new T();
public CircleShape(double x, double y, double radius)
{
this.x = x; this.y = y; this.radius = radius;
}
// low-level (i.e. Implementation-specific)
public void Draw() { drawingAPI.DrawCircle(x, y, radius); }
// high-level (i.e. Abstraction-specific)
public void ResizeByPercentage(double pct) { radius *= pct; }
}
/** "Client" */
class BridgePattern {
public static void Main(string[] args) {
IShape[] shapes = new IShape[2];
shapes[0] = new CircleShape<DrawingAPI1>(1, 2, 3);
shapes[1] = new CircleShape<DrawingAPI2>(5, 7, 11);
foreach (IShape shape in shapes) {
shape.ResizeByPercentage(2.5);
shape.Draw();
}
}
}
The following Python program illustrates the "shape" example given above and will output:
API1.circle at 1:2 7.5 API2.circle at 5:7 27.5
# Implementor
class DrawingAPI:
def drawCircle(x, y, radius):
pass
# ConcreteImplementor 1/2
class DrawingAPI1(DrawingAPI):
def drawCircle(self, x, y, radius):
print("API1.circle at %f:%f radius %f" % (x, y, radius))
# ConcreteImplementor 2/2
class DrawingAPI2(DrawingAPI):
def drawCircle(self, x, y, radius):
print("API2.circle at %f:%f radius %f" % (x, y, radius))
# Abstraction
class Shape:
# low-level
def draw(self):
pass
# high-level
def resizeByPercentage(self, pct):
pass
# Refined Abstraction
class CircleShape(Shape):
def __init__(self, x, y, radius, drawingAPI):
self.__x = x
self.__y = y
self.__radius = radius
self.__drawingAPI = drawingAPI
# low-level i.e. Implementation specific
def draw(self):
self.__drawingAPI.drawCircle(self.__x, self.__y, self.__radius)
# high-level i.e. Abstraction specific
def resizeByPercentage(self, pct):
self.__radius *= pct
def main():
shapes = [
CircleShape(1, 2, 3, DrawingAPI1()),
CircleShape(5, 7, 11, DrawingAPI2())
]
for shape in shapes:
shape.resizeByPercentage(2.5)
shape.draw()
if __name__ == "__main__":
main()
An example in Ruby.
class Abstraction
def initialize(implementor)
@implementor = implementor
end
def operation
raise 'Implementor object does not respond to the operation method' unless @implementor.respond_to?(:operation)
@implementor.operation
end
end
class RefinedAbstraction < Abstraction
def operation
puts 'Starting operation... '
super
end
end
class Implementor
def operation
puts 'Doing necessary stuff'
end
end
class ConcreteImplementorA < Implementor
def operation
super
puts 'Doing additional stuff'
end
end
class ConcreteImplementorB < Implementor
def operation
super
puts 'Doing other additional stuff'
end
end
normal_with_a = Abstraction.new(ConcreteImplementorA.new)
normal_with_a.operation
# Doing necessary stuff
# Doing additional stuff
normal_with_b = Abstraction.new(ConcreteImplementorB.new)
normal_with_b.operation
# Doing necessary stuff
# Doing other additional stuff
refined_with_a = RefinedAbstraction.new(ConcreteImplementorA.new)
refined_with_a.operation
# Starting operation...
# Doing necessary stuff
# Doing additional stuff
refined_with_b = RefinedAbstraction.new(ConcreteImplementorB.new)
refined_with_b.operation
# Starting operation...
# Doing necessary stuff
# Doing other additional stuff
A Scala implementation of the Java drawing example with the same output.
/** "Implementor" */
trait DrawingAPI {
def drawCircle(x:Double, y:Double, radius:Double)
}
/** "ConcreteImplementor" 1/2 */
class DrawingAPI1 extends DrawingAPI {
def drawCircle(x:Double, y:Double, radius:Double) {
printf("API1.circle at %f:%f radius %f\n", x, y, radius)
}
}
/** "ConcreteImplementor" 2/2 */
class DrawingAPI2 extends DrawingAPI {
def drawCircle(x:Double, y:Double, radius:Double) {
printf("API2.circle at %f:%f radius %f\n", x, y, radius)
}
}
/** "Abstraction" */
trait Shape {
def draw() // low-level
def resizeByPercentage(pct:Double) // high-level
}
/** "Refined Abstraction" */
class CircleShape(var x:Double, var y:Double,
var radius:Double, val drawingAPI:DrawingAPI) extends Shape {
// low-level i.e. Implementation specific
def draw() = drawingAPI.drawCircle(x, y, radius)
// high-level i.e. Abstraction specific
def resizeByPercentage(pct:Double) = radius *= pct
}
/** "Client" */
val shapes = List(
new CircleShape(1, 2, 3, new DrawingAPI1),
new CircleShape(5, 7, 11, new DrawingAPI2)
)
shapes foreach { shape =>
shape.resizeByPercentage(2.5)
shape.draw()
}
An example in D.
import std.stdio;
/** "Implementor" */
interface DrawingAPI {
void drawCircle(double x, double y, double radius);
}
/** "ConcreteImplementor" 1/2 */
class DrawingAPI1: DrawingAPI {
void drawCircle(double x, double y, double radius) {
writefln("\nAPI1.circle at %f:%f radius %f", x, y, radius);
}
}
/** "ConcreteImplementor" 2/2 */
class DrawingAPI2: DrawingAPI {
void drawCircle(double x, double y, double radius) {
writefln("\nAPI2.circle at %f:%f radius %f", x, y, radius);
}
}
/** "Abstraction" */
interface Shape {
void draw(); // low-level
void resizeByPercentage(double pct); // high-level
}
/** "Refined Abstraction" */
class CircleShape: Shape {
this(double x, double y, double radius, DrawingAPI drawingAPI) {
this.x = x;
this.y = y;
this.radius = radius;
this.drawingAPI = drawingAPI;
}
// low-level i.e. Implementation specific
void draw() {
drawingAPI.drawCircle(x, y, radius);
}
// high-level i.e. Abstraction specific
void resizeByPercentage(double pct) {
radius *= pct;
}
private:
double x, y, radius;
DrawingAPI drawingAPI;
}
int main(string[] argv) {
auto api1 = new DrawingAPI1();
auto api2 = new DrawingAPI2();
auto c1 = new CircleShape(1, 2, 3, api1);
auto c2 = new CircleShape(5, 7, 11, api2);
Shape[4] shapes;
shapes[0] = c1;
shapes[1] = c2;
shapes[0].resizeByPercentage(2.5);
shapes[0].draw();
shapes[1].resizeByPercentage(2.5);
shapes[1].draw();
return 0;
}
This example in Perl uses the MooseX::Declare module.
# Implementor
role Drawing::API {
requires 'draw_circle';
}
# Concrete Implementor 1
class Drawing::API::1 with Drawing::API {
method draw_circle(Num $x, Num $y, Num $r) {
printf "API1.circle at %f:%f radius %f\n", $x, $y, $r;
}
}
# Concrete Implementor 2
class Drawing::API::2 with Drawing::API {
method draw_circle(Num $x, Num $y, Num $r) {
printf "API2.circle at %f:%f radius %f\n", $x, $y, $r;
}
}
# Abstraction
role Shape {
requires qw( draw resize );
}
# Refined Abstraction
class Shape::Circle with Shape {
has $_ => ( is => 'rw', isa => 'Any' ) for qw( x y r );
has api => ( is => 'ro', does => 'Drawing::API' );
method draw() {
$self->api->draw_circle( $self->x, $self->y, $self->r );
}
method resize(Num $percentage) {
$self->{r} *= $percentage;
}
}
my @shapes = (
Shape::Circle->new( x=>1, y=>2, r=>3, api => Drawing::API::1->new ),
Shape::Circle->new( x=>5, y=>7, r=>11, api => Drawing::API::2->new ),
)
$_->resize( 2.5 ) and $_->draw for @shapes;
The following Delphi program illustrates the "shape" example given above and will output:
API1.circle at 1:2 7.5 API2.circle at 5:7 27.5
program Bridge;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
///implementator
TDrawingAPI = class abstract
procedure DrawCircle(x, y, radius: double); virtual; abstract;
end;
//ConcreteImplementator 1
TDrawingAPI1 = class(TDrawingAPI)
procedure DrawCircle(x, y, radius: double); override;
end;
//ConcreteImplementator 2
TDrawingAPI2 = class(TDrawingAPI)
procedure DrawCircle(x, y, radius: double);override;
end;
//Abstraction
TShape = class abstract
procedure Draw();virtual; abstract;// low-level (i.e. Implementation-specific)
procedure ResizeByPercentage(pct: double);virtual; abstract;// high-level (i.e. Abstraction-specific)
end;
//Refined Abstraction
TCircleShape = class(TShape)
strict private
x, y, radius: double;
drawingAPI: TDrawingAPI;
public
constructor Create(x, y, radius: double; drawingAPI: TDrawingAPI);
procedure Draw;override;
procedure ResizeByPercentage(pct: double);override;
end;
{ TDeawingAPI1 }
procedure TDrawingAPI1.DrawCircle(x, y, radius: double);
begin
WriteLn('API1.circle at '+FloatToStr(x)+' : '+FloatToStr(y)+' radius '+FloatToStr(radius));
end;
{ TDeawingAPI }
procedure TDrawingAPI2.DrawCircle(x, y, radius: double);
begin
WriteLn('API2.circle at '+FloatToStr(x)+' : '+FloatToStr(y)+' radius '+FloatToStr(radius));
end;
{ TCircleShape }
constructor TCircleShape.Create(x, y, radius: double; drawingAPI: TDrawingAPI);
begin
self.x := x;
self.y := y;
self.radius := radius;
self.drawingAPI := drawingAPI;
end;
procedure TCircleShape.Draw;
begin
drawingAPI.DrawCircle(x, y, radius);
end;
procedure TCircleShape.ResizeByPercentage(pct: double);
begin
radius := radius * pct;
end;
var shapes: array of TShape;
shape: TShape;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
SetLength(shapes, 2);
shapes[0] := TCircleShape.Create(1, 2, 3, TDrawingAPI1.Create);
shapes[1] := TCircleShape.Create(5, 7, 11, TDrawingAPI2.Create);
for shape in shapes do
begin
shape.ResizeByPercentage(2.5);
shape.Draw;
end;
WriteLn(#13#10+'Press any key to continue..');
ReadLn;
shapes[0].Free;
shapes[1].Free;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Builder
[edit | edit source]
The builder pattern is useful for avoiding a huge list of constructors for a class. Let's imagine a class that stores the mode of transport (of an employee for instance). Here is the constructor that takes a MetroLine object as a parameter:
modeOfTransport(MetroLine) |
Now we need a constructor for someone who uses the car, the bus or the train:
new modeOfTransport(MetroLine)
new modeOfTransport(Train) |
For some of them, we need to indicate a travel allowance:
new modeOfTransport(MetroLine)
new modeOfTransport(Train, Integer) |
We have employees who use several modes of transport to go to work. However, we realize that the list of constructors is now becoming a mess. Each new parameter leads to an exponential duplication of constructors. If some parameters have the same type, it becomes very confusing. A solution to this issue would be to first build a fake object and then fill it by calling methods on it:
new modeOfTransport(MetroLine)
modeOfTransport.setTravelAllowance(Integer) |
The list of methods is no longer exponential but the state of the object may be inconsistent. A better solution would be to set all the parameters to an object of another class, a pre-constructor, and then pass this object to the constructor of ModeOfTransport:
modeOfTransportPreConstructor.setMetroLine(MetroLine)
new modeOfTransport(ModeOfTransportPreConstructor) |
This solution is even better. We only have a single valid ModeOfTransport object. However, the ModeOfTransport constructor can be called with a half-filled pre-constructor. So the pre-constructor should be a builder and should have a method that returns the ModeOfTransport object. This method will only return an object if the builder has been correctly filled, otherwise it returns null:
modeOfTransportBuilder.setMetroLine(MetroLine)
modeOfTransport := modeOfTransportBuilder.getResult() |
So the solution is to use a builder class. Let's see the structure of the code in an UML class diagram:
- Builder: Abstract interface for creating objects (product).
- Concrete Builder: Provides implementation for Builder. It is an object able to construct other objects. Constructs and assembles parts to build the objects.
The builder pattern can be used for objects that contain flat data (html code, SQL query, X.509 certificate...), that is to say data that can't be easily edited. This type of data can not be edited step by step and must be edited all at once. The best way to construct such an object is to use a builder class.
Examples
In Java, the StringBuffer
and StringBuilder
classes follow the builder design pattern. They are used to build String
objects.
Cost
You can easily decide to use it. At worst, the pattern is useless.
Creation
Starting from a plain old class with a public constructor, implementing the design pattern is not very expensive. You can create the builder class alongside your code. Then you will have to remove the existing constructor calls to use the builder instead. The refactoring is hardly automatic.
Maintenance
This design pattern has only small drawbacks. It may lead to small redundancies between the class and the builder structures but the both class have usually different structures. However, it is expensive to convert to an abstract factory.
Removal
The refactoring is hardly automatic. It should be done manually.
Advices
- Put the builder term in the name of the builder class to indicate the use of the pattern to the other developers.
- Build your builder class as a fluent interface. It would increase the pattern interest.
- If the target class contains flat data, your builder class can be constructed as a Composite that implements the Interpreter pattern.
Implementations
Building a car.
/**
* Can have GPS, trip computer and a various number of seaters. Can be a city car, a sport car or a cabriolet.
*/
public class Car {
/**
* The description of the car.
*/
private String description = null;
/**
* Construct and return the car.
* @param aDescription The description of the car.
*/
public Car(String aDescription) {
description = aDescription;
}
/**
* Print the car.
* @return A flat representation.
*/
public String toString() {
return description;
}
}
/**
*
*/
public class CarBuilder {
/**
* Sport car.
*/
private static final int SPORT_CAR = 1;
/**
* City car.
*/
private static final int CITY_CAR = 2;
/**
* Cabriolet.
*/
private static final int CABRIOLET = 3;
/**
* The type of the car.
*/
private int carType;
/**
* True if the car has a trip computer.
*/
private boolean hasTripComputer;
/**
* True if the car has a GPS.
*/
private boolean hasGPS;
/**
* The number of seaters the car may have.
*/
private int seaterNumber;
/**
* Construct and return the car.
* @return a Car with the right options.
*/
public Car getResult() {
return new Car((carType == CITY_CAR) ? "A city car" : ((carType == SPORT_CAR) ? "A sport car" : "A cabriolet")
+ " with " + seaterNumber + " seaters"
+ (hasTripComputer ? " with a trip computer" : "")
+ (hasGPS ? " with a GPS" : "")
+ ".");
}
/**
* Tell the builder the number of seaters.
* @param number the number of seaters the car may have.
*/
public void setSeaters(int number) {
seaterNumber = number;
}
/**
* Make the builder remember that the car is a city car.
*/
public void setCityCar() {
carType = CITY_CAR;
}
/**
* Make the builder remember that the car is a cabriolet.
*/
public void setCabriolet() {
carType = CABRIOLET;
}
/**
* Make the builder remember that the car is a sport car.
*/
public void setSportCar() {
carType = SPORT_CAR;
}
/**
* Make the builder remember that the car has a trip computer.
*/
public void setTripComputer() {
hasTripComputer = true;
}
/**
* Make the builder remember that the car has not a trip computer.
*/
public void unsetTripComputer() {
hasTripComputer = false;
}
/**
* Make the builder remember that the car has a global positioning system.
*/
public void setGPS() {
hasGPS = true;
}
/**
* Make the builder remember that the car has not a global positioning system.
*/
public void unsetGPS() {
hasGPS = false;
}
}
/**
* Construct a CarBuilder called carBuilder and build a car.
*/
public class Director {
public static void main(String[] args) {
CarBuilder carBuilder = new CarBuilder();
carBuilder.setSeaters(2);
carBuilder.setSportCar();
carBuilder.setTripComputer();
carBuilder.unsetGPS();
Car car = carBuilder.getResult();
System.out.println(car);
}
}
It will produce:
A sport car with 2 seaters with a trip computer.
Building a pizza.
/** "Product" */
class Pizza {
private String dough = "";
private String sauce = "";
private String topping = "";
public void setDough(final String dough) {
this.dough = dough;
}
public void setSauce(final String sauce) {
this.sauce = sauce;
}
public void setTopping(final String topping) {
this.topping = topping;
}
}
/** "Abstract Builder" */
abstract class PizzaBuilder {
protected Pizza pizza;
public abstract void buildDough();
public abstract void buildSauce();
public abstract void buildTopping();
public void createNewPizzaProduct() {
this.pizza = new Pizza();
}
public Pizza getPizza() {
return this.pizza;
}
}
/** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
@Override public void buildDough() {
this.pizza.setDough("cross");
}
@Override public void buildSauce() {
this.pizza.setSauce("mild");
}
@Override public void buildTopping() {
this.pizza.setTopping("ham+pineapple");
}
}
/** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
@Override public void buildDough() {
this.pizza.setDough("pan baked");
}
@Override public void buildSauce() {
this.pizza.setSauce("hot");
}
@Override public void buildTopping() {
this.pizza.setTopping("pepperoni+salami");
}
}
/** "Director" */
class Waiter {
private PizzaBuilder pizzaBuilder;
public void setPizzaBuilder(final PizzaBuilder pb) {
this.pizzaBuilder = pb;
}
public Pizza getPizza() {
return this.pizzaBuilder.getPizza();
}
public void constructPizza() {
this.pizzaBuilder.createNewPizzaProduct();
this.pizzaBuilder.buildDough();
this.pizzaBuilder.buildSauce();
this.pizzaBuilder.buildTopping();
}
}
/** A customer ordering a pizza. */
class BuilderExample {
public static void main(final String[] args) {
final Waiter waiter = new Waiter();
final PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
final PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();
waiter.setPizzaBuilder(hawaiianPizzaBuilder);
waiter.constructPizza();
final Pizza pizza = waiter.getPizza();
waiter.setPizzaBuilder(spicyPizzaBuilder);
waiter.constructPizza();
final Pizza anotherPizza = waiter.getPizza();
}
}
The Director assembles a bicycle instance in the example above, delegating the construction to a separate builder object that has been given to the Director by the Client.
/// <summary>
/// Represents a product created by the builder.
/// </summary>
public class Bicycle
{
public Bicycle(string make, string model, string colour, int height)
{
Make = make;
Model = model;
Colour = colour;
Height = height;
}
public string Make { get; set; }
public string Model { get; set; }
public int Height { get; set; }
public string Colour { get; set; }
}
/// <summary>
/// The builder abstraction.
/// </summary>
public interface IBicycleBuilder
{
Bicycle GetResult();
string Colour { get; set; }
int Height { get; set; }
}
/// <summary>
/// Concrete builder implementation.
/// </summary>
public class GTBuilder : IBicycleBuilder
{
public Bicycle GetResult()
{
return Height == 29 ? new Bicycle("GT", "Avalanche", Colour, Height) : null;
}
public string Colour { get; set; }
public int Height { get; set; }
}
/// <summary>
/// The director.
/// </summary>
public class MountainBikeBuildDirector
{
private IBicycleBuilder _builder;
public MountainBikeBuildDirector(IBicycleBuilder builder)
{
_builder = builder;
}
public void Construct()
{
_builder.Colour = "Red";
_builder.Height = 29;
}
public Bicycle GetResult()
{
return this._builder.GetResult();
}
}
public class Client
{
public void DoSomethingWithBicycles()
{
var director = new MountainBikeBuildDirector(new GTBuilder());
// Director controls the stepwise creation of product and returns the result.
director.Construct();
Bicycle myMountainBike = director.GetResult();
}
}
Another example:
using System;
namespace BuilderPattern
{
// Builder - abstract interface for creating objects (the product, in this case)
abstract class PizzaBuilder
{
protected Pizza pizza;
public Pizza GetPizza()
{
return pizza;
}
public void CreateNewPizzaProduct()
{
pizza = new Pizza();
}
public abstract void BuildDough();
public abstract void BuildSauce();
public abstract void BuildTopping();
}
// Concrete Builder - provides implementation for Builder; an object able to construct other objects.
// Constructs and assembles parts to build the objects
class HawaiianPizzaBuilder : PizzaBuilder
{
public override void BuildDough()
{
pizza.dough = "cross";
}
public override void BuildSauce()
{
pizza.sauce = "mild";
}
public override void BuildTopping()
{
pizza.topping = "ham+pineapple";
}
}
// Concrete Builder - provides implementation for Builder; an object able to construct other objects.
// Constructs and assembles parts to build the objects
class SpicyPizzaBuilder : PizzaBuilder
{
public override void BuildDough()
{
pizza.dough = "pan baked";
}
public override void BuildSauce()
{
pizza.sauce = "hot";
}
public override void BuildTopping()
{
pizza.topping = "pepperoni + salami";
}
}
// Director - responsible for managing the correct sequence of object creation.
// Receives a Concrete Builder as a parameter and executes the necessary operations on it.
class Cook
{
private PizzaBuilder _pizzaBuilder;
public void SetPizzaBuilder(PizzaBuilder pb)
{
_pizzaBuilder = pb;
}
public Pizza GetPizza()
{
return _pizzaBuilder.GetPizza();
}
public void ConstructPizza()
{
_pizzaBuilder.CreateNewPizzaProduct();
_pizzaBuilder.BuildDough();
_pizzaBuilder.BuildSauce();
_pizzaBuilder.BuildTopping();
}
}
// Product - The final object that will be created by the Director using Builder
public class Pizza
{
public string dough = string.Empty;
public string sauce = string.Empty;
public string topping = string.Empty;
}
class Program
{
static void Main(string[] args)
{
PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
Cook cook = new Cook();
cook.SetPizzaBuilder(hawaiianPizzaBuilder);
cook.ConstructPizza();
// create the product
Pizza hawaiian = cook.GetPizza();
PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();
cook.SetPizzaBuilder(spicyPizzaBuilder);
cook.ConstructPizza();
// create another product
Pizza spicy = cook.GetPizza();
}
}
}
This C++11 implementation is based on the pre C++98 implementation in the book.
#include <iostream>
enum Direction {North, South, East, West};
class MapSite {
public:
virtual void enter() = 0;
virtual ~MapSite() = default;
};
class Room : public MapSite {
public:
Room() :roomNumber(0) {}
Room(int n) :roomNumber(n) {}
void setSide(Direction d, MapSite* ms) {
std::cout << "Room::setSide " << d << ' ' << ms << '\n';
}
virtual void enter() {}
Room(const Room&) = delete; // rule of three
Room& operator=(const Room&) = delete;
private:
int roomNumber;
};
class Wall : public MapSite {
public:
Wall() {}
virtual void enter() {}
};
class Door : public MapSite {
public:
Door(Room* r1 = nullptr, Room* r2 = nullptr)
:room1(r1), room2(r2) {}
virtual void enter() {}
Door(const Door&) = delete; // rule of three
Door& operator=(const Door&) = delete;
private:
Room* room1;
Room* room2;
};
class Maze {
public:
void addRoom(Room* r) {
std::cout << "Maze::addRoom " << r << '\n';
}
Room* roomNo(int) const {
return nullptr;
}
};
class MazeBuilder {
public:
virtual ~MazeBuilder() = default;
virtual void buildMaze() = 0;
virtual void buildRoom(int room) = 0;
virtual void buildDoor(int roomFrom, int roomTo) = 0;
virtual Maze* getMaze() {
return nullptr;
}
protected:
MazeBuilder() = default;
};
// If createMaze is passed an object that can create a new maze in its entirety using operations for adding rooms, doors, and walls to the maze it builds, then you can use inheritance to change parts of the maze or the way the maze is built. This is an example of the Builder (110) pattern.
class MazeGame {
public:
Maze* createMaze(MazeBuilder& builder) {
builder.buildMaze();
builder.buildRoom(1);
builder.buildRoom(2);
builder.buildDoor(1, 2);
return builder.getMaze();
}
Maze* CreateComplexMaze(MazeBuilder& builder) {
builder.buildRoom(1);
// ...
builder.buildRoom(1001);
return builder.getMaze();
}
};
class StandardMazeBuilder : public MazeBuilder {
public:
StandardMazeBuilder() :currentMaze(nullptr) {}
virtual void buildMaze() {
currentMaze = new Maze;
}
virtual void buildRoom(int n) {
if (!currentMaze->roomNo(n)) {
Room* room = new Room(n);
currentMaze->addRoom(room);
room->setSide(North, new Wall);
room->setSide(South, new Wall);
room->setSide(East, new Wall);
room->setSide(West, new Wall);
}
}
virtual void buildDoor(int n1, int n2) {
Room* r1 = currentMaze->roomNo(n1);
Room* r2 = currentMaze->roomNo(n2);
Door* d = new Door(r1, r2);
r1->setSide(commonWall(r1,r2), d);
r2->setSide(commonWall(r2,r1), d);
}
virtual Maze* getMaze() {
return currentMaze;
}
StandardMazeBuilder(const StandardMazeBuilder&) = delete; // rule of three
StandardMazeBuilder& operator=(const StandardMazeBuilder&) = delete;
private:
Direction commonWall(Room*, Room*) {
return North;
}
Maze* currentMaze;
};
int main() {
MazeGame game;
StandardMazeBuilder builder;
game.createMaze(builder);
builder.getMaze();
}
The program output is like:
Maze::addRoom 0x2145ed0
Room::setSide 0 0x2146300
Room::setSide 1 0x2146320
Room::setSide 2 0x2146340
Room::setSide 3 0x2146360
Maze::addRoom 0x2146380
Room::setSide 0 0x21463a0
Room::setSide 1 0x21463c0
Room::setSide 2 0x21463e0
Room::setSide 3 0x2146400
Room::setSide 0 0x2146420
Room::setSide 0 0x2146420
Another example:
#include <string>
#include <iostream>
using namespace std;
// "Product"
class Pizza {
public:
void dough(const string& dough) {
dough_ = dough;
}
void sauce(const string& sauce) {
sauce_ = sauce;
}
void topping(const string& topping) {
topping_ = topping;
}
void open() const {
cout << "Pizza with " << dough_ << " dough, " << sauce_ << " sauce and "
<< topping_ << " topping. Mmm." << endl;
}
private:
string dough_;
string sauce_;
string topping_;
};
// "Abstract Builder"
class PizzaBuilder {
public:
// Chinmay Mandal : This default constructor may not be required here
PizzaBuilder()
{
// Chinmay Mandal : Wrong syntax
// pizza_ = new Pizza;
}
const Pizza& pizza() {
return pizza_;
}
virtual void buildDough() = 0;
virtual void buildSauce() = 0;
virtual void buildTopping() = 0;
protected:
Pizza pizza_;
};
class HawaiianPizzaBuilder : public PizzaBuilder {
public:
void buildDough() {
pizza_.dough("cross");
}
void buildSauce() {
pizza_.sauce("mild");
}
void buildTopping() {
pizza_.topping("ham+pineapple");
}
};
class SpicyPizzaBuilder : public PizzaBuilder {
public:
void buildDough() {
pizza_.dough("pan baked");
}
void buildSauce() {
pizza_.sauce("hot");
}
void buildTopping() {
pizza_.topping("pepperoni+salami");
}
};
class Cook {
public:
Cook()
: pizzaBuilder_(NULL/*nullptr*/)//Chinmay Mandal : nullptr replaced with NULL.
{ }
~Cook() {
if (pizzaBuilder_)
delete pizzaBuilder_;
}
void pizzaBuilder(PizzaBuilder* pizzaBuilder) {
if (pizzaBuilder_)
delete pizzaBuilder_;
pizzaBuilder_ = pizzaBuilder;
}
const Pizza& getPizza() {
return pizzaBuilder_->pizza();
}
void constructPizza() {
pizzaBuilder_->buildDough();
pizzaBuilder_->buildSauce();
pizzaBuilder_->buildTopping();
}
private:
PizzaBuilder* pizzaBuilder_;
};
int main() {
Cook cook;
cook.pizzaBuilder(new HawaiianPizzaBuilder);
cook.constructPizza();
Pizza hawaiian = cook.getPizza();
hawaiian.open();
cook.pizzaBuilder(new SpicyPizzaBuilder);
cook.constructPizza();
Pizza spicy = cook.getPizza();
spicy.open();
}
<?php
/** "Product" */
class Pizza {
protected $dough;
protected $sauce;
protected $topping;
public function setDough($dough) {
$this->dough = $dough;
}
public function setSauce($sauce) {
$this->sauce = $sauce;
}
public function setTopping($topping) {
$this->topping = $topping;
}
public function showIngredients() {
echo "Dough : ".$this->dough."<br/>";
echo "Sauce : ".$this->sauce."<br/>";
echo "Topping : ".$this->topping."<br/>";
}
}
/** "Abstract Builder" */
abstract class PizzaBuilder {
protected $pizza;
public function getPizza() {
return $this->pizza;
}
public function createNewPizzaProduct() {
$this->pizza = new Pizza();
}
public abstract function buildDough();
public abstract function buildSauce();
public abstract function buildTopping();
}
/** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
public function buildDough() {
$this->pizza->setDough("cross");
}
public function buildSauce() {
$this->pizza->setSauce("mild");
}
public function buildTopping() {
$this->pizza->setTopping("ham + pineapple");
}
}
/** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
public function buildDough() {
$this->pizza->setDough("pan baked");
}
public function buildSauce() {
$this->pizza->setSauce("hot");
}
public function buildTopping() {
$this->pizza->setTopping("pepperoni + salami");
}
}
/** "Director" */
class Waiter {
protected $pizzaBuilder;
public function setPizzaBuilder(PizzaBuilder $pizzaBuilder) {
$this->pizzaBuilder = $pizzaBuilder;
}
public function getPizza() {
return $this->pizzaBuilder->getPizza();
}
public function constructPizza() {
$this->pizzaBuilder->createNewPizzaProduct();
$this->pizzaBuilder->buildDough();
$this->pizzaBuilder->buildSauce();
$this->pizzaBuilder->buildTopping();
}
}
class Tester {
public static function main() {
$oWaiter = new Waiter();
$oHawaiianPizzaBuilder = new HawaiianPizzaBuilder();
$oSpicyPizzaBuilder = new SpicyPizzaBuilder();
$oWaiter->setPizzaBuilder($oHawaiianPizzaBuilder);
$oWaiter->constructPizza();
$pizza = $oWaiter->getPizza();
$pizza->showIngredients();
echo "<br/>";
$oWaiter->setPizzaBuilder($oSpicyPizzaBuilder);
$oWaiter->constructPizza();
$pizza = $oWaiter->getPizza();
$pizza->showIngredients();
}
}
Tester::main();
output :
Dough : cross Sauce : mild Topping : ham + pineapple
Dough : pan baked Sauce : hot Topping : pepperoni + salami
# Product
class Pizza
attr_accessor :dough, :sauce, :topping
end
# Abstract Builder
class PizzaBuilder
def get_pizza
@pizza
end
def create_new_pizza_product
@pizza = Pizza.new
end
def build_dough; end
def build_sauce; end
def build_topping; end
end
# ConcreteBuilder
class HawaiianPizzaBuilder < PizzaBuilder
def build_dough
@pizza.dough = 'cross'
end
def build_sauce
@pizza.sauce = 'mild'
end
def build_topping
@pizza.topping = 'ham+pineapple'
end
end
# ConcreteBuilder
class SpicyPizzaBuilder < PizzaBuilder
def build_dough
@pizza.dough = 'pan baked'
end
def build_sauce
@pizza.sauce = 'hot'
end
def build_topping
@pizza.topping = 'pepperoni+salami'
end
end
# Director
class Waiter
attr_accessor :pizza_builder
def get_pizza
pizza_builder.get_pizza
end
def construct_pizza
pizza_builder.create_new_pizza_product
pizza_builder.build_dough
pizza_builder.build_sauce
pizza_builder.build_topping
end
end
# A customer ordering a pizza.
class BuilderExample
def main(args = [])
waiter = Waiter.new
hawaiian_pizza_builder = HawaiianPizzaBuilder.new
spicy_pizza_builder = SpicyPizzaBuilder.new
waiter.pizza_builder = hawaiian_pizza_builder
waiter.construct_pizza
pizza = waiter.get_pizza
end
end
puts BuilderExample.new.main.inspect
class Animal:
"""
Abstract Animal
"""
legs = 0
tail = False
roar = ''
class Mutator:
"""
Mutator
"""
def mutate(self):
self.animal = Animal()
class Cat(Mutator):
"""
Cat
"""
def create_legs(self):
self.animal.legs = 4
def create_tail(self):
self.animal.tail = True
def create_roar(self):
self.animal.roar = 'meowww!'
class Dog(Mutator):
"""
Dog
"""
def create_legs(self):
self.animal.legs = 4
def create_tail(self):
self.animal.tail = True
def create_roar(self):
self.animal.roar = 'woffff!'
class AnimalOwner:
"""
Farm owner
"""
__mutator = ''
def set_animal(self, mutator):
self.__mutator = mutator
def create_an_animal_for_me(self):
self.__mutator.mutate()
self.__mutator.create_legs()
self.__mutator.create_tail()
self.__mutator.create_roar()
def get_animal(self):
return self.__mutator.animal
c = Cat()
d = Dog()
ao = AnimalOwner()
ao.set_animal(c)
ao.create_an_animal_for_me()
animal = ao.get_animal()
print(animal.roar) # meowww!
program Builder;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
(*Product - final object that will be created by Director using Builder*)
TPizza = class
fDough: string;
fSauce: string;
fTopping: string;
procedure Open;
end;
(*Builder - abstract class as interface for creating objects -> product in this case*)
TPizzaBuilder = class abstract
protected
fPizza: TPizza;
public
function GetPizza: TPizza;
procedure CreateNewPizzaProduct;
procedure BuildDough; virtual; abstract;
procedure BuildSauce; virtual; abstract;
procedure BuildTopping; virtual; abstract;
end;
(*concrete builder - provides implementation for Builder *)
(*an object able to construct other objects.*)
THawaiianPizzaBuilder = class(TPizzaBuilder)
public
procedure BuildDough; override;
procedure BuildSauce; override;
procedure BuildTopping; override;
end;
(*concrete builder = provides implenentation for Builder*)
(*an object able to construct other objects.*)
TSpicyPizzaBuilder = class(TPizzaBuilder)
public
procedure BuildDough; override;
procedure BuildSauce; override;
procedure BuildTopping; override;
end;
(*Director - responsible for managing the correct sequence of object creation.*)
(*Receives a Concrete Builder as a parameter and executes the necessary operations on it.*)
TCook = class
protected
fPizzaBuilder: TPizzaBuilder;
public
procedure SetPizzaBuilder(pb: TPizzaBuilder);
function GetPizza: TPizza;
procedure ConstructPizza;
end;
{ THawaiianPizzaBuilder }
procedure THawaiianPizzaBuilder.BuildDough;
begin
fPizza.fDough:= 'cross';
end;
procedure THawaiianPizzaBuilder.BuildSauce;
begin
fPizza.fSauce:= 'mild';
end;
procedure THawaiianPizzaBuilder.BuildTopping;
begin
fPizza.fTopping:= 'ham + pineapple';
end;
{ TSpicyPizzaBuilder }
procedure TSpicyPizzaBuilder.BuildDough;
begin
fPizza.fDough:= 'pan baked';
end;
procedure TSpicyPizzaBuilder.BuildSauce;
begin
fPizza.fSauce:= 'hot';
end;
procedure TSpicyPizzaBuilder.BuildTopping;
begin
fPizza.fTopping:= 'pepperoni + salami';
end;
{ TCook }
procedure TCook.ConstructPizza;
begin
fPizzaBuilder.CreateNewPizzaProduct;
fPizzaBuilder.BuildDough;
fPizzaBuilder.BuildSauce;
fPizzaBuilder.BuildTopping;
end;
function TCook.GetPizza: TPizza;
begin
Result:= fPizzaBuilder.GetPizza;
end;
procedure TCook.SetPizzaBuilder(pb: TPizzaBuilder);
begin
fPizzaBuilder:= pb;
end;
{ TPizzaBuilder }
procedure TPizzaBuilder.CreateNewPizzaProduct;
begin
fPizza:= TPizza.Create;
end;
function TPizzaBuilder.GetPizza: TPizza;
begin
Result:= fPizza;
end;
{ TPizza }
procedure TPizza.Open;
begin
WriteLn('Pizza with: ' + fDough + ' dough, ' +
fSauce +' souce and '+fTopping +' topping. Mmm.');
end;
var
cook: TCook;
hawaiian, spicy: TPizza;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
cook:= TCook.Create;
cook.SetPizzaBuilder(THawaiianPizzaBuilder.Create);
cook.ConstructPizza;
WriteLn('(* create the product *)');
hawaiian:= cook.GetPizza;
hawaiian.Open;
WriteLn(#13#10+'(* create another product *)');
cook.SetPizzaBuilder(TSpicyPizzaBuilder.Create);
cook.ConstructPizza;
spicy:= cook.GetPizza;
spicy.Open;
WriteLn(#13#10+'Press any key to continue...');
ReadLn;
spicy.Free;
hawaiian.Free;
cook.Free;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Chain of responsibility
[edit | edit source]
Various examples of the Chain of responsibility pattern.
Below is an example of this pattern in Java. A logger is created using a chain of loggers, each one configured with different log levels.
import java.util.Arrays;
import java.util.EnumSet;
import java.util.function.Consumer;
@FunctionalInterface
public interface Logger {
public enum LogLevel {
INFO, DEBUG, WARNING, ERROR, FUNCTIONAL_MESSAGE, FUNCTIONAL_ERROR;
public static LogLevel[] all() {
return values();
}
}
abstract void message(String msg, LogLevel severity);
default Logger appendNext(Logger nextLogger) {
return (msg, severity) -> {
message(msg, severity);
nextLogger.message(msg, severity);
};
}
static Logger writeLogger(LogLevel[] levels, Consumer<String> stringConsumer) {
EnumSet<LogLevel> set = EnumSet.copyOf(Arrays.asList(levels));
return (msg, severity) -> {
if (set.contains(severity)) {
stringConsumer.accept(msg);
}
};
}
static Logger consoleLogger(LogLevel... levels) {
return writeLogger(levels, msg -> System.err.println("Writing to console: " + msg));
}
static Logger emailLogger(LogLevel... levels) {
return writeLogger(levels, msg -> System.err.println("Sending via email: " + msg));
}
static Logger fileLogger(LogLevel... levels) {
return writeLogger(levels, msg -> System.err.println("Writing to Log File: " + msg));
}
}
class Runner {
public static void main(String[] args) {
// Build an immutable chain of responsibility
Logger logger = consoleLogger(LogLevel.all())
.appendNext(emailLogger(LogLevel.FUNCTIONAL_MESSAGE, LogLevel.FUNCTIONAL_ERROR))
.appendNext(fileLogger(LogLevel.WARNING, LogLevel.ERROR));
// Handled by consoleLogger since the console has a LogLevel of all
logger.message("Entering function ProcessOrder().", LogLevel.DEBUG);
logger.message("Order record retrieved.", LogLevel.INFO);
// Handled by consoleLogger and emailLogger since emailLogger implements Functional_Error & Functional_Message
logger.message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel.FUNCTIONAL_ERROR);
logger.message("Order Dispatched.", LogLevel.FUNCTIONAL_MESSAGE);
// Handled by consoleLogger and fileLogger since fileLogger implements Warning & Error
logger.message("Customer Address details missing in Branch DataBase.", LogLevel.WARNING);
logger.message("Customer Address details missing in Organization DataBase.", LogLevel.ERROR);
}
}
The following Java code illustrates the pattern with the example of a logging class. Each logging handler decides if any action is to be taken at this log level and then passes the message on to the next logging handler. Note that this example should not be seen as a recommendation on how to write logging classes.
Also, note that in a 'pure' implementation of the chain of responsibility pattern, a logger would not pass responsibility further down the chain after handling a message. In this example, a message will be passed down the chain whether it is handled or not.
abstract class Logger {
public static final int ERR = 3;
public static final int NOTICE = 5;
public static final int DEBUG = 7;
private int mask;
// The next element in the chain of responsibility
private Logger next;
public Logger(int mask) {
this.mask = mask;
}
public Logger setNext(Logger l) {
next = l;
return l;
}
public void message(String msg, int priority) {
if (priority <= mask) {
writeMessage(msg);
}
if (next != null) {
next.message(msg, priority);
}
}
abstract protected void writeMessage(String msg);
}
class StdoutLogger extends Logger {
public StdoutLogger(int mask) {
super(mask);
}
protected void writeMessage(String msg) {
System.out.println("Writing to stdout: " + msg);
}
}
class EmailLogger extends Logger {
public EmailLogger(int mask) {
super(mask);
}
protected void writeMessage(String msg) {
System.out.println("Sending via email: " + msg);
}
}
class StderrLogger extends Logger {
public StderrLogger(int mask) {
super(mask);
}
protected void writeMessage(String msg) {
System.err.println("Sending to stderr: " + msg);
}
}
public class ChainOfResponsibilityExample {
public static void main(String[] args) {
// Build the chain of responsibility
Logger l,l1;
l1 = l = new StdoutLogger(Logger.DEBUG);
l1 = l1.setNext(new EmailLogger(Logger.NOTICE));
l1 = l1.setNext(new StderrLogger(Logger.ERR));
// Handled by StdoutLogger
l.message("Entering function y.", Logger.DEBUG);
// Handled by StdoutLogger and EmailLogger
l.message("Step1 completed.", Logger.NOTICE);
// Handled by all three loggers
l.message("An error has occurred.", Logger.ERR);
}
}
The output is:
Writing to stdout: Entering function y. Writing to stdout: Step1 completed. Sending via e-mail: Step1 completed. Writing to stdout: An error has occurred. Sending via e-mail: An error has occurred. Writing to stderr: An error has occurred.
Below is another example of this pattern in Java. In this example we have different roles, each having a fix purchase power limit and a successor. Every time a user in a role receives a purchase request, when it's over his limit, he just passes that request to his successor.
The PurchasePower abstract class with the abstract method processRequest.
abstract class PurchasePower {
protected double final base = 500;
protected PurchasePower successor;
public void setSuccessor(PurchasePower successor) {
this.successor = successor;
}
abstract public void processRequest(PurchaseRequest request);
}
Four implementations of the abstract class above: Manager, Director, Vice President, President
class ManagerPPower extends PurchasePower {
private double final ALLOWABLE = 10 * base;
public void processRequest(PurchaseRequest request) {
if(request.getAmount() < ALLOWABLE) {
System.out.println("Manager will approve $"+ request.getAmount());
}
else if(successor != null) {
successor.processRequest(request);
}
}
}
class DirectorPPower extends PurchasePower {
private double final ALLOWABLE = 20 * base;
public void processRequest(PurchaseRequest request) {
if(request.getAmount() < ALLOWABLE) {
System.out.println("Director will approve $"+ request.getAmount());
}
else if(successor != null) {
successor.processRequest(request);
}
}
}
class VicePresidentPPower extends PurchasePower {
private double final ALLOWABLE = 40 * base;
public void processRequest(PurchaseRequest request) {
if(request.getAmount() < ALLOWABLE) {
System.out.println("Vice President will approve $" + request.getAmount());
}
else if(successor != null) {
successor.processRequest(request);
}
}
}
class PresidentPPower extends PurchasePower {
private double final ALLOWABLE = 60 * base;
public void processRequest(PurchaseRequest request) {
if(request.getAmount() < ALLOWABLE) {
System.out.println("President will approve $" + request.getAmount());
}
else {
System.out.println( "Your request for $" + request.getAmount() + " needs a board meeting!");
}
}
}
The PurchaseRequest class with its Getter methods which keeps the request data in this example.
class PurchaseRequest {
private int number;
private double amount;
private String purpose;
public PurchaseRequest(int number, double amount, String purpose) {
this.number = number;
this.amount = amount;
this.purpose = purpose;
}
public double getAmount() {
return amount;
}
public void setAmount(double amt) {
amount = amt;
}
public String getPurpose() {
return purpose;
}
public void setPurpose(String reason) {
purpose = reason;
}
public int getNumber(){
return number;
}
public void setNumber(int num) {
number = num;
}
}
And here a usage example, the successors are set like this: Manager -> Director -> Vice President -> President
class CheckAuthority {
public static void main(String[] args) {
ManagerPPower manager = new ManagerPPower();
DirectorPPower director = new DirectorPPower();
VicePresidentPPower vp = new VicePresidentPPower();
PresidentPPower president = new PresidentPPower();
manager.setSuccessor(director);
director.setSuccessor(vp);
vp.setSuccessor(president);
//enter ctrl+c to kill.
try{
while (true) {
System.out.println("Enter the amount to check who should approve your expenditure.");
System.out.print(">");
double d = Double.parseDouble(new BufferedReader(new InputStreamReader(System.in)).readLine());
manager.processRequest(new PurchaseRequest(0, d, "General"));
}
}
catch(Exception e){
System.exit(1);
}
}
}
"""
Chain of responsibility pattern example.
"""
from abc import ABCMeta, abstractmethod
from enum import Enum, auto
class LogLevel(Enum):
""" Log Levels Enum."""
NONE = auto()
INFO = auto()
DEBUG = auto()
WARNING = auto()
ERROR = auto()
FUNCTIONAL_MESSAGE = auto()
FUNCTIONAL_ERROR = auto()
ALL = auto()
class Logger:
"""Abstract handler in chain of responsibility pattern."""
__metaclass__ = ABCMeta
next = None
def __init__(self, levels) -> None:
"""Initialize new logger.
Arguments:
levels (list[str]): List of log levels.
"""
self.log_levels = []
for level in levels:
self.log_levels.append(level)
def set_next(self, next_logger: Logger):
"""Set next responsible logger in the chain.
Arguments:
next_logger (Logger): Next responsible logger.
Returns: Logger: Next responsible logger.
"""
self.next = next_logger
return self.next
def message(self, msg: str, severity: LogLevel) -> None:
"""Message writer handler.
Arguments:
msg (str): Message string.
severity (LogLevel): Severity of message as log level enum.
"""
if LogLevel.ALL in self.log_levels or severity in self.log_levels:
self.write_message(msg)
if self.next is not None:
self.next.message(msg, severity)
@abstractmethod
def write_message(self, msg: str) -> None:
"""Abstract method to write a message.
Arguments:
msg (str): Message string.
Raises: NotImplementedError
"""
raise NotImplementedError("You should implement this method.")
class ConsoleLogger(Logger):
def write_message(self, msg: str) -> None:
"""Overrides parent's abstract method to write to console.
Arguments:
msg (str): Message string.
"""
print("Writing to console:", msg)
class EmailLogger(Logger):
def write_message(self, msg: str) -> None:
"""Overrides parent's abstract method to send an email.
Arguments:
msg (str): Message string.
"""
print(f"Sending via email: {msg}")
class FileLogger(Logger):
def write_message(self, msg: str) -> None:
"""Overrides parent's abstract method to write a file.
Arguments:
msg (str): Message string.
"""
print(f"Writing to log file: {msg}")
def main():
"""Building the chain of responsibility."""
logger = ConsoleLogger([LogLevel.ALL])
email_logger = logger.set_next(
EmailLogger([LogLevel.FUNCTIONAL_MESSAGE, LogLevel.FUNCTIONAL_ERROR])
)
# As we don't need to use file logger instance anywhere later
# We will not set any value for it.
email_logger.set_next(
FileLogger([LogLevel.WARNING, LogLevel.ERROR])
)
# ConsoleLogger will handle this part of code since the message
# has a log level of all
logger.message("Entering function ProcessOrder().", LogLevel.DEBUG)
logger.message("Order record retrieved.", LogLevel.INFO)
# ConsoleLogger and FileLogger will handle this part since file logger
# implements WARNING and ERROR
logger.message(
"Customer Address details missing in Branch DataBase.",
LogLevel.WARNING
)
logger.message(
"Customer Address details missing in Organization DataBase.",
LogLevel.ERROR
)
# ConsoleLogger and EmailLogger will handle this part as they implement
# functional error
logger.message(
"Unable to Process Order ORD1 Dated D1 for customer C1.",
LogLevel.FUNCTIONAL_ERROR
)
logger.message("OrderDispatched.", LogLevel.FUNCTIONAL_MESSAGE)
if __name__ == "__main__":
main()
Another example:
class Car:
def __init__(self):
self.name = None
self.km = 11100
self.fuel = 5
self.oil = 5
def handle_fuel(car):
if car.fuel < 10:
print "added fuel"
car.fuel = 100
def handle_km(car):
if car.km > 10000:
print "made a car test."
car.km = 0
def handle_oil(car):
if car.oil < 10:
print "Added oil"
car.oil = 100
class Garage:
def __init__(self):
self.handlers = []
def add_handler(self, handler):
self.handlers.append(handler)
def handle_car(self, car):
for handler in self.handlers:
handler(car)
if __name__ == '__main__':
handlers = [handle_fuel, handle_km, handle_oil]
garage = Garage()
for handle in handlers:
garage.add_handler(handle)
garage.handle_car(Car())
enum LogLevel
None
Info
Debug
Warning
Error
FunctionalMessage
FunctionalError
All
end
abstract class Logger
property log_levels
property next : Logger | Nil
def initialize(*levels)
@log_levels = [] of LogLevel
levels.each do |level|
@log_levels << level
end
end
def message(msg : String, severity : LogLevel)
if @log_levels.includes?(LogLevel::All) || @log_levels.includes?(severity)
write_message(msg)
end
@next.try(&.message(msg, severity))
end
abstract def write_message(msg : String)
end
class ConsoleLogger < Logger
def write_message(msg : String)
puts "Writing to console: #{msg}"
end
end
class EmailLogger < Logger
def write_message(msg : String)
puts "Sending via email: #{msg}"
end
end
class FileLogger < Logger
def write_message(msg : String)
puts "Writing to Log File: #{msg}"
end
end
# Program
# Build the chain of responsibility
logger = ConsoleLogger.new(LogLevel::All)
logger1 = logger.next = EmailLogger.new(LogLevel::FunctionalMessage, LogLevel::FunctionalError)
logger2 = logger1.next = FileLogger.new(LogLevel::Warning, LogLevel::Error)
# Handled by ConsoleLogger since the console has a loglevel of all
logger.message("Entering function ProcessOrder().", LogLevel::Debug)
logger.message("Order record retrieved.", LogLevel::Info)
# Handled by ConsoleLogger and FileLogger since filelogger implements Warning & Error
logger.message("Customer Address details missing in Branch DataBase.", LogLevel::Warning)
logger.message("Customer Address details missing in Organization DataBase.", LogLevel::Error)
# Handled by ConsoleLogger and EmailLogger as it implements functional error
logger.message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel::FunctionalError)
# Handled by ConsoleLogger and EmailLogger
logger.message("Order Dispatched.", LogLevel::FunctionalMessage)
Output
Writing to console: Entering function ProcessOrder(). Writing to console: Order record retrieved. Writing to console: Customer Address details missing in Branch DataBase. Writing to Log File: Customer Address details missing in Branch DataBase. Writing to console: Customer Address details missing in Organization DataBase. Writing to Log File: Customer Address details missing in Organization DataBase. Writing to console: Unable to Process Order ORD1 Dated D1 For Customer C1. Sending via email: Unable to Process Order ORD1 Dated D1 For Customer C1. Writing to console: Order Dispatched. Sending via email: Order Dispatched.
<?php
abstract class Logger
{
/**
* Bitmask flags for severity.
*/
public const NONE = 0;
public const INFO = 0b000001;
public const DEBUG = 0b000010;
public const WARNING = 0b000100;
public const ERROR = 0b001000;
public const FUNCTIONAL_MESSAGE = 0b010000;
public const FUNCTIONAL_ERROR = 0b100000;
public const ALL = 0b111111;
/** @var int A bitmask flag from this class. */
protected int $logMask;
/** @var \Logger|null An optional next logger to handle the message */
protected ?Logger $next = null;
/**
* Logger constructor.
*
* @param int $mask
* A bitmask flag from this class.
*/
public function __construct(int $mask)
{
$this->logMask = $mask;
}
/**
* Set next responsible logger in the chain.
*
* @param \Logger $nextLogger
* Next responsible logger.
*
* @return \Logger
* Logger: Next responsible logger.
*/
public function setNext(Logger $nextLogger): Logger
{
$this->next = $nextLogger;
return $nextLogger;
}
/**
* Message writer handler.
*
* @param string $msg
* Message string.
* @param int $severity
* Severity of message as a bitmask flag from this class.
*
* @return $this
*/
public function message(string $msg, int $severity): Logger
{
if ($severity & $this->logMask) {
$this->writeMessage($msg);
}
if ($this->next !== null) {
$this->next->message($msg, $severity);
}
return $this;
}
/**
* Abstract method to write a message
*
* @param string $msg
* Message string.
*/
abstract protected function writeMessage(string $msg): void;
}
class ConsoleLogger extends Logger
{
protected function writeMessage(string $msg): void
{
echo "Writing to console: $msg\n";
}
}
class EmailLogger extends Logger
{
protected function writeMessage(string $msg): void
{
echo "Sending via email: $msg\n";
}
}
class FileLogger extends Logger
{
protected function writeMessage(string $msg): void
{
echo "Writing to a log file: $msg\n";
}
}
$logger = new ConsoleLogger(Logger::ALL);
$logger
->setNext(new EmailLogger(Logger::FUNCTIONAL_MESSAGE | Logger::FUNCTIONAL_ERROR))
->setNext(new FileLogger(Logger::WARNING | Logger::ERROR));
$logger
// Handled by ConsoleLogger since the console has a loglevel of all
->message("Entering function ProcessOrder().", Logger::DEBUG)
->message("Order record retrieved.", Logger::INFO)
// Handled by ConsoleLogger and FileLogger since filelogger implements Warning & Error
->message("Customer Address details missing in Branch DataBase.", Logger::WARNING)
->message("Customer Address details missing in Organization DataBase.", Logger::ERROR)
// Handled by ConsoleLogger and EmailLogger as it implements functional error
->message("Unable to Process Order ORD1 Dated D1 For Customer C1.", Logger::FUNCTIONAL_ERROR)
// Handled by ConsoleLogger and EmailLogger
->message("Order Dispatched.", Logger::FUNCTIONAL_MESSAGE);
/* Output
Writing to console: Entering function ProcessOrder().
Writing to console: Order record retrieved.
Writing to console: Customer Address details missing in Branch DataBase.
Writing to a log file: Customer Address details missing in Branch DataBase.
Writing to console: Customer Address details missing in Organization DataBase.
Writing to a log file: Customer Address details missing in Organization DataBase.
Writing to console: Unable to Process Order ORD1 Dated D1 For Customer C1.
Sending via email: Unable to Process Order ORD1 Dated D1 For Customer C1.
Writing to console: Order Dispatched.
Sending via email: Order Dispatched.
*/
#lang racket
; Define an automobile structure
(struct auto (fuel km oil) #:mutable #:transparent)
; Create an instance of an automobile
(define the-auto (auto 5 1500 7))
; Define handlers
(define (handle-fuel auto)
(when (< (auto-fuel auto) 10)
(begin (set-auto-fuel! auto 10)
(printf "set fuel\n"))))
(define (handle-km auto)
(when (> (auto-km auto) 10000)
(begin (set-auto-km! auto 0)
(printf "made a car test\n"))))
(define (handle-oil auto)
(when (< (auto-oil auto) 10)
(begin (set-auto-oil! auto (+ (auto-oil auto) 5))
(printf "added oil\n"))))
; Apply each handler to the auto
(define (handle-auto handlers auto)
(unless (null? handlers)
(begin ((car handlers) auto)
(handle-auto (cdr handlers) auto))))
(display the-auto)
(newline)
; Handle the auto
(handle-auto (list handle-fuel handle-km handle-oil) the-auto)
(display the-auto)
(newline)
Java example about purchase power of various roles, using perl 5.10 and Moose.
use feature ':5.10';
package PurchasePower;
use Moose;
has successor => ( is => "rw", isa => "PurchasePower" );
sub processRequest {
my ( $self, $req ) = @_;
if ( $req->amount < $self->allowable ) {
printf "%s will approve \$%.2f\n", $self->title, $req->amount;
}
elsif ( $self->successor ) {
$self->successor->processRequest($req);
}
else {
$self->no_match( $req );
}
}
package ManagerPPower;
use Moose; extends "PurchasePower";
sub allowable {5000}
sub title {"manager"}
package DirectorPPower;
use Moose; extends "PurchasePower";
sub allowable {10000}
sub title {"director"}
package VicePresidentPPower;
use Moose; extends "PurchasePower";
sub allowable {20000}
sub title {"vice-president"}
package PresidentPPower;
use Moose; extends "PurchasePower";
sub allowable {30000}
sub title {"president"}
sub no_match {
my ( $self, $req ) = @_;
printf "your request for \$%.2f will need a board meeting\n", $req->amount;
}
package PurchaseRequest;
use Moose;
has number => ( is => "rw", isa => "Int" );
has amount => ( is => "rw", isa => "Num" );
has purpose => ( is => "rw", isa => "Str" );
package main;
my $manager = new ManagerPPower;
my $director = new DirectorPPower;
my $vp = new VicePresidentPPower;
my $president = new PresidentPPower;
$manager->successor($director);
$director->successor($vp);
$vp->successor($president);
print "Enter the amount to check who should approve your expenditure.\n>";
my $amount = readline;
$manager->processRequest(
PurchaseRequest->new(
number => 0,
amount => $amount,
purpose => "General"
)
);
Perl example using perl 5.10 and Moose.
use feature ':5.10';
package Car;
use Moose;
has name => ( is => "rw", default => undef );
has km => ( is => "rw", default => 11100 );
has fuel => ( is => "rw", default => 5 );
has oil => ( is => "rw", default => 5 );
sub handle_fuel {
my $self = shift;
if ( $self->fuel < 10 ) {
say "added fuel";
$self->fuel(100);
}
}
sub handle_km {
my $self = shift;
if ( $self->km > 10000 ) {
say "made a car test";
$self->km(0);
}
}
sub handle_oil {
my $self = shift;
if ( $self->oil < 10 ) {
say "added oil";
$self->oil(100);
}
}
package Garage;
use Moose;
has handler => (
is => "ro",
isa => "ArrayRef[Str]",
traits => ['Array'],
handles => { add_handler => "push", handlers => "elements" },
default => sub { [] }
);
sub handle_car {
my ($self, $car) = @_;
$car->$_ for $self->handlers
}
package main;
my @handlers = qw( handle_fuel handle_km handle_oil );
my $garage = Garage->new;
$garage->add_handler($_) for @handlers;
$garage->handle_car( Car->new );
This C# examples uses the logger application to select different sources based on the log level;
namespace ChainOfResponsibility;
[Flags]
public enum LogLevel
{
None = 0, // 0
Info = 1, // 1
Debug = 2, // 10
Warning = 4, // 100
Error = 8, // 1000
FunctionalMessage = 16, // 10000
FunctionalError = 32, // 100000
All = 63 // 111111
}
/// <summary>
/// Abstract Handler in chain of responsibility pattern.
/// </summary>
public abstract class Logger
{
protected LogLevel logMask;
// The next Handler in the chain
protected Logger next;
public Logger(LogLevel mask)
{
this.logMask = mask;
}
/// <summary>
/// Sets the Next logger to make a list/chain of Handlers.
/// </summary>
public Logger SetNext(Logger nextlogger)
{
Logger lastLogger = this;
while (lastLogger.next != null)
{
lastLogger = lastLogger.next;
}
lastLogger.next = nextlogger;
return this;
}
public void Message(string msg, LogLevel severity)
{
if ((severity & logMask) != 0) // True only if any of the logMask bits are set in severity
{
WriteMessage(msg);
}
if (next != null)
{
next.Message(msg, severity);
}
}
abstract protected void WriteMessage(string msg);
}
public class ConsoleLogger : Logger
{
public ConsoleLogger(LogLevel mask)
: base(mask)
{ }
protected override void WriteMessage(string msg)
{
Console.WriteLine("Writing to console: " + msg);
}
}
public class EmailLogger : Logger
{
public EmailLogger(LogLevel mask)
: base(mask)
{ }
protected override void WriteMessage(string msg)
{
// Placeholder for mail send logic, usually the email configurations are saved in config file.
Console.WriteLine("Sending via email: " + msg);
}
}
class FileLogger : Logger
{
public FileLogger(LogLevel mask)
: base(mask)
{ }
protected override void WriteMessage(string msg)
{
// Placeholder for File writing logic
Console.WriteLine("Writing to Log File: " + msg);
}
}
public class Program
{
public static void Main(string[] args)
{
// Build the chain of responsibility
Logger logger;
logger = new ConsoleLogger(LogLevel.All)
.SetNext(new EmailLogger(LogLevel.FunctionalMessage | LogLevel.FunctionalError))
.SetNext(new FileLogger(LogLevel.Warning | LogLevel.Error));
// Handled by ConsoleLogger since the console has a loglevel of all
logger.Message("Entering function ProcessOrder().", LogLevel.Debug);
logger.Message("Order record retrieved.", LogLevel.Info);
// Handled by ConsoleLogger and FileLogger since filelogger implements Warning & Error
logger.Message("Customer Address details missing in Branch DataBase.", LogLevel.Warning);
logger.Message("Customer Address details missing in Organization DataBase.", LogLevel.Error);
// Handled by ConsoleLogger and EmailLogger as it implements functional error
logger.Message("Unable to Process Order ORD1 Dated D1 For Customer C1.", LogLevel.FunctionalError);
// Handled by ConsoleLogger and EmailLogger
logger.Message("Order Dispatched.", LogLevel.FunctionalMessage);
}
}
/* Output
Writing to console: Entering function ProcessOrder().
Writing to console: Order record retrieved.
Writing to console: Customer Address details missing in Branch DataBase.
Writing to Log File: Customer Address details missing in Branch DataBase.
Writing to console: Customer Address details missing in Organization DataBase.
Writing to Log File: Customer Address details missing in Organization DataBase.
Writing to console: Unable to Process Order ORD1 Dated D1 For Customer C1.
Sending via email: Unable to Process Order ORD1 Dated D1 For Customer C1.
Writing to console: Order Dispatched.
Sending via email: Order Dispatched.
*/
Another example:
using System;
class MainApp
{
static void Main()
{
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.SetSuccessor(h2);
h2.SetSuccessor(h3);
// Generate and process request
int[] requests = {2, 5, 14, 22, 18, 3, 27, 20};
foreach (int request in requests)
{
h1.HandleRequest(request);
}
// Wait for user
Console.Read();
}
}
// "Handler"
abstract class Handler
{
protected Handler successor;
public void SetSuccessor(Handler successor)
{
this.successor = successor;
}
public abstract void HandleRequest(int request);
}
// "ConcreteHandler1"
class ConcreteHandler1 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 0 && request < 10)
{
Console.WriteLine("{0} handled request {1}",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
// "ConcreteHandler2"
class ConcreteHandler2 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 10 && request < 20)
{
Console.WriteLine("{0} handled request {1}",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
// "ConcreteHandler3"
class ConcreteHandler3 : Handler
{
public override void HandleRequest(int request)
{
if (request >= 20 && request < 30)
{
Console.WriteLine("{0} handled request {1}",
this.GetType().Name, request);
}
else if (successor != null)
{
successor.HandleRequest(request);
}
}
}
Command
[edit | edit source]
The command pattern is an object behavioural pattern that decouples sender and receiver. It can also be thought as an object-oriented equivalent of a call back method. Call back: It is a function that is registered to be called at a later point of time based on user actions.
Scope
Object
Purpose
Behavioral
Intent
Encapsulate the request for a service as an object.
Applicability
- to parameterize objects with an action to perform
- to specify, queue, and execute requests at different times
- for a history of requests
- for multilevel undo/redo
Structure
Consequences
- + abstracts executor of a service
- + supports arbitrary-level undo-redo
- + composition yields macro-commands
- - might result in lots of trivial command subclasses
Examples
The best example for this pattern is the graphical user interface. On most multidata interfaces, you have both a "New" menu and a "New" button with an icon like in Libre Office Writer. Both controls are connected to a command object, so the action is performed by the same code.
Cost
This pattern is dealing with the whole architecture of a program. It may have a substantial impact on the project.
Creation
If the code already exists, this pattern is very expensive.
Maintenance
This pattern is very expensive to maintain.
Removal
This pattern is very expensive to remove, too.
Advises
- Use the Command term to indicate the use of the pattern to the other developers.
Implementations
Consider a "simple" switch. In this example we configure the Switch with two commands: to turn the light on and to turn the light off. A benefit of this particular implementation of the command pattern is that the switch can be used with any device, not just a light — the Switch in the following example turns a light on and off, but the Switch's constructor is able to accept any subclasses of Command for its two parameters. For example, you could configure the Switch to start an engine.
/* The Command interface */
public interface Command {
void execute();
}
import java.util.List;
import java.util.ArrayList;
/* The Invoker class */
public class Switch {
private List<Command> history = new ArrayList<Command>();
public Switch() {
}
public void storeAndExecute(Command cmd) {
this.history.add(cmd); // optional
cmd.execute();
}
}
/* The Receiver class */
public class Light {
public Light() {
}
public void turnOn() {
System.out.println("The light is on");
}
public void turnOff() {
System.out.println("The light is off");
}
}
/* The Command for turning on the light - ConcreteCommand #1 */
public class FlipUpCommand implements Command {
private Light theLight;
public FlipUpCommand(Light light) {
this.theLight = light;
}
public void execute(){
theLight.turnOn();
}
}
/* The Command for turning off the light - ConcreteCommand #2 */
public class FlipDownCommand implements Command {
private Light theLight;
public FlipDownCommand(Light light) {
this.theLight = light;
}
public void execute() {
theLight.turnOff();
}
}
/* The test class or client */
public class PressSwitch {
public static void main(String[] args){
// Check number of arguments
if (args.length != 1) {
System.err.println("Argument \"ON\" or \"OFF\" is required.");
System.exit(-1);
}
Light lamp = new Light();
Command switchUp = new FlipUpCommand(lamp);
Command switchDown = new FlipDownCommand(lamp);
// See criticism of this model above:
// The switch itself should not be aware of lamp details (switchUp, switchDown)
// either directly or indirectly
Switch mySwitch = new Switch();
switch (args[0]) {
case "ON":
mySwitch.storeAndExecute(switchUp);
break;
case "OFF":
mySwitch.storeAndExecute(switchDown);
break;
default:
System.err.println("Argument \"ON\" or \"OFF\" is required.");
System.exit(-1);
}
}
}
Operations
The implementations to do are:
- copying a command before putting it on a history list
- handling hysteresis
- supporting transactions
public interface Command {
public int execute(int a, int b);
}
public class AddCommand implements Command {
public int execute(int a, int b) {
return a + b;
}
}
public class MultCommand implements Command {
public int execute(int a, int b) {
return a * b;
}
}
public class TestCommand {
public static void main(String a[]) {
Command add = new AddCommand();
add.execute(1, 2); // returns 3
Command multiply = new MultCommand();
multiply.execute(2, 3); // returns 6
}
}
In the above example, it can be noted that the command pattern decouples the object that invokes the operation from the ones having the knowledge to perform it.
Command in Java
Menus and buttons provide a classic example of the need for the command pattern. When you add a menu to an application, you have to configure the menu with words that describe actions that the user can choose, such as Save and Open. Similarly for a button. You also have to configure the menu or button so that it can take action, calling a method in response to a user's click. However, JMenuItem or JButton class has no way of knowing what action to perform when an item or button is selected. In the following example we use the same Action for both a menu item and a button saving us from having to write the same code twice.
Action actionOpen = new AbstractAction("Open...", iconOpen) {
public void actionPerformed(ActionEvent e) {
... // open a file
}
}
JMenu mFile = new JMenu("File");
JMenuItem item = mFile.add(actionOpen); // use the same action for both a menu item ...
JToolBar m_toolBar = new JToolBar();
JButton bOpen = new JButton(actionOpen); // ... and a button
m_toolBar.add(bOpen);
Java Swing applications commonly apply the Mediator pattern, registering a single object to receive all GUI events. This object mediates the interaction of the components and translates user input into commands for business domain objects.
Undo in Java
Swing provides for Undo/Redo functionality.
import javax.swing.undo.*;
UndoManager undoManager = new UndoManager();
Action undoAction, redoAction;
undoAction = new AbstractAction("Undo",
new ImageIcon("edit_undo.gif")) {
public void actionPerformed(ActionEvent e) {
try {
undoManager.undo(); // undoManager.redo();
}
catch (CannotUndoException ex) {
System.err.println("Unable to undo: " + ex);
}
updateUndo();
}
};
// same for Redo
protected void updateUndo() {
if(undo.canUndo()) {
undoAction.setEnabled(true);
undoAction.putValue(Action.NAME, undo.getUndoPresentationName());
} else {
undoAction.setEnabled(false);
undoAction.putValue(Action.NAME, "Undo");
}
if(undo.canRedo()) {
redoAction.setEnabled(true);
redoAction.putValue(Action.NAME, undo.getRedoPresentationName());
} else {
redoAction.setEnabled(false);
redoAction.putValue(Action.NAME, "Redo");
}
}
Consider a "simple" switch. In this example we configure the Switch with two commands: to turn the light on and to turn the light off.
A benefit of this particular implementation of the command pattern is that the switch can be used with any device, not just a light. The Switch in the following C# implementation turns a light on and off, but the Switch's constructor is able to accept any subclasses of Command for its two parameters. For example, you could configure the Switch to start an engine.
using System;
namespace CommandPattern;
public interface ICommand
{
void Execute();
}
/* The Invoker class */
public class Switch
{
ICommand _closedCommand;
ICommand _openedCommand;
public Switch(ICommand closedCommand, ICommand openedCommand)
{
_closedCommand = closedCommand;
_openedCommand = openedCommand;
}
// Close the circuit / power on
public void Close()
{
_closedCommand.Execute();
}
// Open the circuit / power off
public void Open()
{
_openedCommand.Execute();
}
}
/* An interface that defines actions that the receiver can perform */
public interface ISwitchable
{
void PowerOn();
void PowerOff();
}
/* The Receiver class */
public class Light : ISwitchable
{
public void PowerOn()
{
Console.WriteLine("The light is on");
}
public void PowerOff()
{
Console.WriteLine("The light is off");
}
}
/* The Command for turning off the device - ConcreteCommand #1 */
public class CloseSwitchCommand : ICommand
{
private ISwitchable _switchable;
public CloseSwitchCommand(ISwitchable switchable)
{
_switchable = switchable;
}
public void Execute()
{
_switchable.PowerOff();
}
}
/* The Command for turning on the device - ConcreteCommand #2 */
public class OpenSwitchCommand : ICommand
{
private ISwitchable _switchable;
public OpenSwitchCommand(ISwitchable switchable)
{
_switchable = switchable;
}
public void Execute()
{
_switchable.PowerOn();
}
}
/* The test class or client */
internal class Program
{
public static void Main(string[] arguments)
{
string argument = arguments.Length > 0 ? arguments[0].ToUpper() : null;
ISwitchable lamp = new Light();
// Pass reference to the lamp instance to each command
ICommand switchClose = new CloseSwitchCommand(lamp);
ICommand switchOpen = new OpenSwitchCommand(lamp);
// Pass reference to instances of the Command objects to the switch
Switch @switch = new Switch(switchClose, switchOpen);
if (argument == "ON")
{
// Switch (the Invoker) will invoke Execute() on the command object.
@switch.Open();
}
else if (argument == "OFF")
{
// Switch (the Invoker) will invoke the Execute() on the command object.
@switch.Close();
}
else
{
Console.WriteLine("Argument \"ON\" or \"OFF\" is required.");
}
}
}
The following code is another implementation of command pattern in C#.
using System;
using System.Collections.Generic;
namespace CommandPattern
{
public interface ICommand
{
void Execute();
}
/* The Invoker class */
public class Switch
{
private List<ICommand> _commands = new List<ICommand>();
public void StoreAndExecute(ICommand command)
{
_commands.Add(command);
command.Execute();
}
}
/* The Receiver class */
public class Light
{
public void TurnOn()
{
Console.WriteLine("The light is on");
}
public void TurnOff()
{
Console.WriteLine("The light is off");
}
}
/* The Command for turning on the light - ConcreteCommand #1 */
public class FlipUpCommand : ICommand
{
private Light _light;
public FlipUpCommand(Light light)
{
_light = light;
}
public void Execute()
{
_light.TurnOn();
}
}
/* The Command for turning off the light - ConcreteCommand #2 */
public class FlipDownCommand : ICommand
{
private Light _light;
public FlipDownCommand(Light light)
{
_light = light;
}
public void Execute()
{
_light.TurnOff();
}
}
/* The test class or client */
internal class Program
{
public static void Main(string[] args)
{
Light lamp = new Light();
ICommand switchUp = new FlipUpCommand(lamp);
ICommand switchDown = new FlipDownCommand(lamp);
Switch s = new Switch();
string arg = args.Length > 0 ? args[0].ToUpper() : null;
if (arg == "ON")
{
s.StoreAndExecute(switchUp);
}
else if (arg == "OFF")
{
s.StoreAndExecute(switchDown);
}
else
{
Console.WriteLine("Argument \"ON\" or \"OFF\" is required.");
}
}
}
}
The following code is an implementation of command pattern in Python.
class Switch(object):
"""The INVOKER class"""
def __init__(self, flip_up_cmd, flip_down_cmd):
self.flip_up = flip_up_cmd
self.flip_down = flip_down_cmd
class Light(object):
"""The RECEIVER class"""
def turn_on(self):
print "The light is on"
def turn_off(self):
print "The light is off"
class LightSwitch(object):
"""The CLIENT class"""
def __init__(self):
lamp = Light()
self._switch = Switch(lamp.turn_on, lamp.turn_off)
def switch(self, cmd):
cmd = cmd.strip().upper()
if cmd == "ON":
self._switch.flip_up()
elif cmd == "OFF":
self._switch.flip_down()
else:
print 'Argument "ON" or "OFF" is required.'
# Execute if this file is run as a script and not imported as a module
if __name__ == "__main__":
light_switch = LightSwitch()
print "Switch ON test."
light_switch.switch("ON")
print "Switch OFF test."
light_switch.switch("OFF")
print "Invalid Command test."
light_switch.switch("****")
/* The Command interface */
trait Command {
def execute()
}
/* The Invoker class */
class Switch {
private var history: List[Command] = Nil
def storeAndExecute(cmd: Command) {
cmd.execute()
this.history :+= cmd
}
}
/* The Receiver class */
class Light {
def turnOn() = println("The light is on")
def turnOff() = println("The light is off")
}
/* The Command for turning on the light - ConcreteCommand #1 */
class FlipUpCommand(theLight: Light) extends Command {
def execute() = theLight.turnOn()
}
/* The Command for turning off the light - ConcreteCommand #2 */
class FlipDownCommand(theLight: Light) extends Command {
def execute() = theLight.turnOff()
}
/* The test class or client */
object PressSwitch {
def main(args: Array[String]) {
val lamp = new Light()
val switchUp = new FlipUpCommand(lamp)
val switchDown = new FlipDownCommand(lamp)
val s = new Switch()
try {
args(0).toUpperCase match {
case "ON" => s.storeAndExecute(switchUp)
case "OFF" => s.storeAndExecute(switchDown)
case _ => println("Argument \"ON\" or \"OFF\" is required.")
}
} catch {
case e: Exception => println("Arguments required.")
}
}
}
The following code is an implementation of command pattern in Javascript.
/* The Invoker function */
var Switch = function(){
this.storeAndExecute = function(command){
command.execute();
}
}
/* The Receiver function */
var Light = function(){
this.turnOn = function(){ console.log ('turn on')};
this.turnOff = function(){ console.log ('turn off') };
}
/* The Command for turning on the light - ConcreteCommand #1 */
var FlipUpCommand = function(light){
this.execute = light.turnOn;
}
/* The Command for turning off the light - ConcreteCommand #2 */
var FlipDownCommand = function(light){
this.execute = light.turnOff;
}
var light = new Light();
var switchUp = new FlipUpCommand(light);
var switchDown = new FlipDownCommand(light);
var s = new Switch();
s.storeAndExecute(switchUp);
s.storeAndExecute(switchDown);
Object subclass: #Switch
instanceVariableNames:
' flipUpCommand flipDownCommand '
classVariableNames: ''
poolDictionaries: ''
Object subclass: #Light
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
Object subclass: #PressSwitch
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
!Switch class methods !
upMessage: flipUpMessage downMessage: flipDownMessage
^self new upMessage: flipUpMessage downMessage: flipDownMessage; yourself.! !
!Switch methods !
upMessage: flipUpMessage downMessage: flipDownMessage
flipUpCommand := flipUpMessage.
flipDownCommand := flipDownMessage.!
flipDown
flipDownCommand perform.!
flipUp
flipUpCommand perform.! !
!Light methods !
turnOff
Transcript show: 'The light is off'; cr.!
turnOn
Transcript show: 'The light is on'; cr.! !
!PressSwitch class methods !
switch: state
" This is the test method "
| lamp switchUp switchDown switch |
lamp := Light new.
switchUp := Message receiver: lamp selector: #turnOn.
switchDown := Message receiver: lamp selector: #turnOff.
switch := Switch upMessage: switchUp downMessage: switchDown.
state = #on ifTrue: [ ^switch flipUp ].
state = #off ifTrue: [ ^switch flipDown ].
Transcript show: 'Argument #on or #off is required.'.
! !
The following code is an implementation of command pattern in PHP.
<?php
interface Command
{
public function execute();
}
/** The Invoker class */
class Switcher
{
private $history = array();
public function storeAndExecute(Command $cmd)
{
$this->history[] = $cmd;
$cmd->execute();
}
}
/** The Receiver class */
class Light
{
public function turnOn()
{
echo("The light is on");
}
public function turnOff()
{
echo("The light is off");
}
}
/** The Command for turning on the light - ConcreteCommand #1 */
class FlipUpCommand implements Command {
private $theLight;
public function __construct(Light $light) {
$this->theLight = $light;
}
public function execute() {
$this->theLight->turnOn();
}
}
/** The Command for turning off the light - ConcreteCommand #2 */
class FlipDownCommand implements Command {
private $theLight;
public function __construct(Light $light) {
$this->theLight = $light;
}
public function execute() {
$this->theLight->turnOff();
}
}
/* The test class or client */
class PressSwitch {
public static function main(string $args){
$lamp = new Light();
$switchUp = new FlipUpCommand($lamp);
$switchDown = new FlipDownCommand($lamp);
$mySwitch = new Switcher();
switch($args) {
case 'ON':
$mySwitch->storeAndExecute($switchUp);
break;
case 'OFF':
$mySwitch->storeAndExecute($switchDown);
break;
default:
echo("Argument \"ON\" or \"OFF\" is required.");
break;
}
}
}
/*INPUT*/
PressSwitch::main('ON'). PHP_EOL;
PressSwitch::main('OFF'). PHP_EOL;
/*OUTPUT*/
//The light is on
//The light is off
Composite
[edit | edit source]
The composite design pattern reduces the cost of an implementation that handles data represented as a tree. When an application does a process on a tree, usually the process has to handle the iteration on the components, the move on the tree and has to process the nodes and the leafs separately. All of this creates a big amount of code. Suppose that you have to handle a file system repository. Each folders can contain files or folders. To handle this, you have an array of items that can be file or folder. The files have a name and the folders are arrays. Now you have to implement a file search operation on the whole folder tree. The pseudo-code should look like this:
method searchFilesInFolders(rootFolder, searchedFileName) is input: a list of the content of the rootFolder. input: the searchedFileName that should be found in the folders. output: the list of encountered files. Empty the foundFiles list Empty the parentFolders list Empty the parentIndices list currentFolder := rootFolder currentIndex := 0 Add rootFolder to parentFolders while parentFolders is not empty do if currentIndex is out of currentFolder then currentFolder := last item of parentFolders Remove the last item of parentFolders currentIndex := last item of parentIndices + 1 Remove the last item of parentIndices else if the item at the currentIndex of the currentFolder is a folder then currentFolder := the folder Add currentFolder to parentFolders Add currentIndex to parentIndices currentIndex := 0 otherwise if the name of the file is equal to the searchedFileName then Add the file to foundFiles Increment currentIndex Return the foundFiles
In the previous code, each iteration of the same while loop is a process of one node or leaf. At the end of the process, the code move to the position of the next node or leaf to process. There are three branches in the loop. The first branch is true when we have processed all the children of the node and it moves to the parent, the second goes into a child node and the last process a leaf (i.e. a file). The memory of the location should be stored to go back in the tree. The problem in this implementation is that it is hardly readable and the process of the folders and the files is completely separate. This code is heavy to maintain and you have to think to the whole tree each moment. The folders and the files should be called the same way so they should be objects that implements the same interface.
- Component
- is the abstraction for all components, including composite ones.
- declares the interface for objects in the composition.
- (optional) defines an interface for accessing a component's parent in the recursive structure, and implements it if that's appropriate.
- Leaf
- represents leaf objects in the composition.
- implements all Component methods.
- Composite
- represents a composite Component (component having children).
- implements methods to manipulate children.
- implements all Component methods, generally by delegating them to its children.
So now the implementation is rather like this:
interface FileSystemComponent is method searchFilesInFolders(searchedFileName) is input: the searchedFileName that should be found in the folders. output: the list of encountered files. class File implementing FileSystemComponent is method searchFilesInFolders(searchedFileName) is input: the searchedFileName that should be found in the folders. output: the list of encountered files. if the name of the file is equal to the searchedFileName then Empty the foundFiles list Add the file to foundFiles Return the foundFiles otherwise Return an empty list class Folder implementing FileSystemComponent is field children is The list of the direct children. method searchFilesInFolders(searchedFileName) is input: the searchedFileName that should be found in the folders. output: the list of encountered files. Empty the foundFiles list for each child in children Call searchFilesInFolders(searchedFileName) on the child Add the result to foundFiles Return the foundFiles
As you can see, a component can be an individual object and also can be a collection of objects. A Composite pattern can represent both the conditions. In this pattern, one can develop tree structures for representing part-whole hierarchies.
Examples
The best example of use of this pattern is the Graphical User Interface. The widgets of the interface are organized in a tree and the operations (resizing, repainting...) on all the widgets are processed using the composite design pattern.
Cost
This pattern is one of the least expensive patterns. You can implement it each time you have to handle a tree of data without worrying. There is no bad usage of this pattern. The cost of the pattern is only to handle the children of a composite but this cost would be required and more expensive without the design pattern.
Creation
You have to create an almost empty interface and implement the management of the composite children. This cost is very low.
Maintenance
You can't get caught in the system. The only relatively expensive situation occurs when you have to often change the operations applied to the whole data tree.
Removal
You should remove the pattern when you remove the data tree. So you just remove all in once. This cost is very low.
Advices
- Put the composite and component terms in the name of the classes to indicate the use of the pattern to the other developers.
Implementations
Various examples of the composite pattern.
using System;
using System.Collections.Generic;
namespace Composite
{
class Program
{
interface IGraphic
{
void Print();
}
class CompositeGraphic : IGraphic
{
private List<IGraphic> child = new List<IGraphic>();
public CompositeGraphic(IEnumerable<IGraphic> collection)
{
child.AddRange(collection);
}
public void Print()
{
foreach(IGraphic g in child)
{
g.Print();
}
}
}
class Ellipse : IGraphic
{
public void Print()
{
Console.WriteLine("Ellipse");
}
}
static void Main(string[] args)
{
new CompositeGraphic(new IGraphic[]
{
new CompositeGraphic(new IGraphic[]
{
new Ellipse(),
new Ellipse(),
new Ellipse()
}),
new CompositeGraphic(new IGraphic[]
{
new Ellipse()
})
}).Print();
}
}
}
The following example, written in Common Lisp, and translated directly from the Java example below it, implements a method named print-graphic, which can be used on either an ellipse, or a list whose elements are either lists or ellipses.
(defstruct ellipse) ;; An empty struct.
;; For the method definitions, "object" is the variable,
;; and the following word is the type.
(defmethod print-graphic ((object null))
NIL)
(defmethod print-graphic ((object cons))
(print-graphic (first object))
(print-graphic (rest object)))
(defmethod print-graphic ((object ellipse))
(print 'ELLIPSE))
(let* ((ellipse-1 (make-ellipse))
(ellipse-2 (make-ellipse))
(ellipse-3 (make-ellipse))
(ellipse-4 (make-ellipse)))
(print-graphic (cons (list ellipse-1 (list ellipse-2 ellipse-3)) ellipse-4)))
The following example, written in Java, implements a graphic class, which can be either an ellipse or a composition of several graphics. Every graphic can be printed. In Backus-Naur form,
Graphic ::= ellipse | GraphicList
GraphicList ::= empty | Graphic GraphicList
It could be extended to implement several other shapes (rectangle, etc.) and methods (translate, etc.).
import java.util.List;
import java.util.ArrayList;
/** "Component" */
interface Graphic {
//Prints the graphic.
public void print();
}
/** "Composite" */
class CompositeGraphic implements Graphic {
//Collection of child graphics.
private final List<Graphic> childGraphics = new ArrayList<>();
//Adds the graphic to the composition.
public void add(Graphic graphic) {
childGraphics.add(graphic);
}
//Prints the graphic.
@Override
public void print() {
for (Graphic graphic : childGraphics) {
graphic.print(); //Delegation
}
}
}
/** "Leaf" */
class Ellipse implements Graphic {
//Prints the graphic.
@Override
public void print() {
System.out.println("Ellipse");
}
}
/** Client */
class CompositeDemo {
public static void main(String[] args) {
//Initialize four ellipses
Ellipse ellipse1 = new Ellipse();
Ellipse ellipse2 = new Ellipse();
Ellipse ellipse3 = new Ellipse();
Ellipse ellipse4 = new Ellipse();
//Creates two composites containing the ellipses
CompositeGraphic compositGraphic2 = new CompositeGraphic();
compositGraphic2.add(ellipse1);
compositGraphic2.add(ellipse2);
compositGraphic2.add(ellipse3);
CompositeGraphic compositGraphic3 = new CompositeGraphic();
compositGraphic3.add(ellipse4);
//Create another graphics that contains two graphics
CompositeGraphic compositGraphic = new CompositeGraphic();
compositGraphic.add(compositGraphic2);
compositGraphic.add(compositGraphic3);
//Prints the complete graphic (Four times the string "Ellipse").
compositGraphic.print();
}
}
The following example, written in Java, implements a graphic class, which can be either an ellipse or a composition of several graphics. Every graphic can be printed. In algebraic form,
Graphic = ellipse | GraphicList GraphicList = empty | Graphic GraphicList
It could be extended to implement several other shapes (rectangle, etc.) and methods (translate, etc.).
/** "Component" */
interface Graphic {
// Prints the graphic.
public void print();
}
/** "Composite" */
import java.util.List;
import java.util.ArrayList;
class CompositeGraphic implements Graphic {
// Collection of child graphics.
private List<Graphic> mChildGraphics = new ArrayList<Graphic>();
// Prints the graphic.
public void print() {
for (Graphic graphic : mChildGraphics) {
graphic.print();
}
}
// Adds the graphic to the composition.
public void add(Graphic graphic) {
mChildGraphics.add(graphic);
}
// Removes the graphic from the composition.
public void remove(Graphic graphic) {
mChildGraphics.remove(graphic);
}
}
/** "Leaf" */
class Ellipse implements Graphic {
// Prints the graphic.
public void print() {
System.out.println("Ellipse");
}
}
/** Client */
public class Program {
public static void main(String[] args) {
// Initialize four ellipses
Ellipse ellipse1 = new Ellipse();
Ellipse ellipse2 = new Ellipse();
Ellipse ellipse3 = new Ellipse();
Ellipse ellipse4 = new Ellipse();
// Initialize three composite graphics
CompositeGraphic graphic = new CompositeGraphic();
CompositeGraphic graphic1 = new CompositeGraphic();
CompositeGraphic graphic2 = new CompositeGraphic();
// Composes the graphics
graphic1.add(ellipse1);
graphic1.add(ellipse2);
graphic1.add(ellipse3);
graphic2.add(ellipse4);
graphic.add(graphic1);
graphic.add(graphic2);
// Prints the complete graphic (four times the string "Ellipse").
graphic.print();
}
}
<?php
/** "Component" */
interface Graphic
{
/**
* Prints the graphic
*
* @return void
*/
public function printOut();
}
/**
* "Composite" - Collection of graphical components
*/
class CompositeGraphic implements Graphic
{
/**
* Collection of child graphics
*
* @var array
*/
private $childGraphics = array();
/**
* Prints the graphic
*
* @return void
*/
public function printOut()
{
foreach ($this->childGraphics as $graphic) {
$graphic->printOut();
}
}
/**
* Adds the graphic to the composition
*
* @param Graphic $graphic Graphical element
*
* @return void
*/
public function add(Graphic $graphic)
{
$this->childGraphics[] = $graphic;
}
/**
* Removes the graphic from the composition
*
* @param Graphic $graphic Graphical element
*
* @return void
*/
public function remove(Graphic $graphic)
{
if (in_array($graphic, $this->childGraphics)) {
unset($this->childGraphics[array_search($graphic, $this->childGraphics)]);
}
}
}
/** "Leaf" */
class Ellipse implements Graphic
{
/**
* Prints the graphic
*
* @return void
*/
public function printOut()
{
echo "Ellipse";
}
}
/** Client */
//Initialize four ellipses
$ellipse1 = new Ellipse();
$ellipse2 = new Ellipse();
$ellipse3 = new Ellipse();
$ellipse4 = new Ellipse();
//Initialize three composite graphics
$graphic = new CompositeGraphic();
$graphic1 = new CompositeGraphic();
$graphic2 = new CompositeGraphic();
//Composes the graphics
$graphic1->add($ellipse1);
$graphic1->add($ellipse2);
$graphic1->add($ellipse3);
$graphic2->add($ellipse4);
$graphic->add($graphic1);
$graphic->add($graphic2);
//Prints the complete graphic (four times the string "Ellipse").
$graphic->printOut();
class Component(object):
def __init__(self, *args, **kw):
pass
def component_function(self): pass
class Leaf(Component):
def __init__(self, *args, **kw):
Component.__init__(self, *args, **kw)
def component_function(self):
print "some function"
class Composite(Component):
def __init__(self, *args, **kw):
Component.__init__(self, *args, **kw)
self.children = []
def append_child(self, child):
self.children.append(child)
def remove_child(self, child):
self.children.remove(child)
def component_function(self):
map(lambda x: x.component_function(), self.children)
c = Composite()
l = Leaf()
l_two = Leaf()
c.append_child(l)
c.append_child(l_two)
c.component_function()
module Component
def do_something
raise NotImplementedError
end
end
class Leaf
include Component
def do_something
puts "Hello"
end
end
class Composite
include Component
attr_accessor :children
def initialize
self.children = []
end
def do_something
children.each {|c| c.do_something}
end
def append_child(child)
children << child
end
def remove_child(child)
children.delete child
end
end
composite = Composite.new
leaf_one = Leaf.new
leaf_two = Leaf.new
composite.append_child(leaf_one)
composite.append_child(leaf_two)
composite.do_something
Decorator
[edit | edit source]
The decorator pattern helps to add behavior or responsibilities to an object. This is also called “Wrapper”.
Examples
Cost
This pattern can be very expensive. You should only use it when it is really necessary. You should have lots of different behaviors and responsibilities for the same class.
Creation
This pattern is expensive to create.
Maintenance
This pattern can be expensive to maintain. If the representation of a class often changes, you will have lots of refactoring.
Removal
This pattern is hard to remove too.
Advises
- Put the decorator term in the name of the decorator classes to indicate the use of the pattern to the other developers.
Implementations
This example illustrates a simple extension method for a bool type.
using System;
// Extension methods must be parts of static classes.
static class BooleanExtensionMethodSample
{
public static void Main()
{
bool yes = true;
bool no = false;
// Toggle the booleans! yes should return false and no should return true.
Console.WriteLine(yes.Toggle());
Console.WriteLine(no.Toggle());
}
// The extension method that adds Toggle to bool.
public static bool Toggle(this bool target)
{
// Return the opposite of the target.
return !target;
}
}
Coffee making scenario
# include <iostream>
# include <string>
// The abstract coffee class
class Coffee
{
public:
virtual double getCost() = 0;
virtual std::string getIngredient() = 0;
virtual ~Coffee() {}
};
// Plain coffee without ingredient
class SimpleCoffee:public Coffee
{
private:
double cost;
std::string ingredient;
public:
SimpleCoffee()
{
cost = 1;
ingredient = std::string("Coffee");
}
double getCost()
{
return cost;
}
std::string getIngredient()
{
return ingredient;
}
};
// Abstract decorator class
class CoffeeDecorator:public Coffee
{
protected:
Coffee & decoratedCoffee;
public:
CoffeeDecorator(Coffee & decoratedCoffee):decoratedCoffee(decoratedCoffee){}
~CoffeeDecorator() {
delete &decoratedCoffee;
}
};
// Milk Decorator
class Milk:public CoffeeDecorator
{
private:
double cost;
public:
Milk(Coffee & decoratedCoffee):CoffeeDecorator(decoratedCoffee)
{
cost = 0.5;
}
double getCost()
{
return cost + decoratedCoffee.getCost();
}
std::string getIngredient()
{
return "Milk "+decoratedCoffee.getIngredient();
}
};
// Whip decorator
class Whip:public CoffeeDecorator
{
private:
double cost;
public:
Whip(Coffee & decoratedCoffee):CoffeeDecorator(decoratedCoffee)
{
cost = 0.7;
}
double getCost()
{
return cost + decoratedCoffee.getCost();
}
std::string getIngredient()
{
return "Whip "+decoratedCoffee.getIngredient();
}
};
// Sprinkles decorator
class Sprinkles:public CoffeeDecorator
{
private:
double cost;
public:
Sprinkles(Coffee & decoratedCoffee):CoffeeDecorator(decoratedCoffee)
{
cost = 0.6;
}
double getCost()
{
return cost + decoratedCoffee.getCost();
}
std::string getIngredient()
{
return "Sprinkles "+decoratedCoffee.getIngredient();
}
};
// Here's a test
int main()
{
Coffee* sample;
sample = new SimpleCoffee();
sample = new Milk(*sample);
sample = new Whip(*sample);
std::cout << sample->getIngredient() << std::endl;
std::cout << "Cost: " << sample->getCost() << std::endl;
delete sample;
}
The output of this program is given below:
Whip Milk Coffee
Cost: 2.2
// Class to be decorated
function Coffee() {
this.cost = function() {
return 1;
};
}
// Decorator A
function Milk(coffee) {
this.cost = function() {
return coffee.cost() + 0.5;
};
}
// Decorator B
function Whip(coffee) {
this.cost = function() {
return coffee.cost() + 0.7;
};
}
// Decorator C
function Sprinkles(coffee) {
this.cost = function() {
return coffee.cost() + 0.2;
};
}
// Here's one way of using it
var coffee = new Milk(new Whip(new Sprinkles(new Coffee())));
alert( coffee.cost() );
// Here's another
var coffee = new Coffee();
coffee = new Sprinkles(coffee);
coffee = new Whip(coffee);
coffee = new Milk(coffee);
alert(coffee.cost());
fun printInfo(c: Coffee) {
println("Cost: " + c.cost + "; Ingredients: " + c.ingredients)
}
fun main(args: Array<String>) {
var c: Coffee = SimpleCoffee()
printInfo(c)
c = WithMilk(c)
printInfo(c)
c = WithSprinkles(c)
printInfo(c)
}
// The interface Coffee defines the functionality of Coffee implemented by decorator
interface Coffee {
val cost: Double // Returns the cost of the coffee
val ingredients: String // Returns the ingredients of the coffee
}
// Extension of a simple coffee without any extra ingredients
class SimpleCoffee : Coffee {
override val cost: Double
get() = 1.0
override val ingredients: String
get() = "Coffee"
}
// Abstract decorator class - note that it implements Coffee interface
abstract class CoffeeDecorator(private val decoratedCoffee: Coffee) : Coffee {
override// Implementing methods of the interface
val cost: Double
get() = decoratedCoffee.cost
override val ingredients: String
get() = decoratedCoffee.ingredients
}
// Decorator WithMilk mixes milk into coffee.
// Note it extends CoffeeDecorator.
class WithMilk(c: Coffee) : CoffeeDecorator(c) {
override// Overriding methods defined in the abstract superclass
val cost: Double
get() = super.cost + 0.5
override val ingredients: String
get() = super.ingredients + ", Milk"
}
// Decorator WithSprinkles mixes sprinkles onto coffee.
// Note it extends CoffeeDecorator.
class WithSprinkles(c: Coffee) : CoffeeDecorator(c) {
override val cost: Double
get() = super.cost + 0.2
override val ingredients: String
get() = super.ingredients + ", Sprinkles"
}
The output of this program is given below:
Cost: 1.0; Ingredients: Coffee
Cost: 1.5; Ingredients: Coffee, Milk
Cost: 1.7; Ingredients: Coffee, Milk, Sprinkles
First Example (window/scrolling scenario)
The following Java example illustrates the use of decorators using the window/scrolling scenario.
// the Window abstract class
public abstract class Window {
public abstract void draw(); // draws the Window
public abstract String getDescription(); // returns a description of the Window
}
// extension of a simple Window without any scrollbars
class SimpleWindow extends Window {
public void draw() {
// draw window
}
public String getDescription() {
return "simple window";
}
}
The following classes contain the decorators for all Window classes, including the decorator classes themselves.
// abstract decorator class - note that it extends Window
abstract class WindowDecorator extends Window {
protected Window decoratedWindow; // the Window being decorated
public WindowDecorator (Window decoratedWindow) {
this.decoratedWindow = decoratedWindow;
}
public void draw() {
decoratedWindow.draw(); //delegation
}
public String getDescription() {
return decoratedWindow.getDescription(); //delegation
}
}
// the first concrete decorator which adds vertical scrollbar functionality
class VerticalScrollBarDecorator extends WindowDecorator {
public VerticalScrollBarDecorator (Window decoratedWindow) {
super(decoratedWindow);
}
@Override
public void draw() {
super.draw();
drawVerticalScrollBar();
}
private void drawVerticalScrollBar() {
// draw the vertical scrollbar
}
@Override
public String getDescription() {
return super.getDescription() + ", including vertical scrollbars";
}
}
// the second concrete decorator which adds horizontal scrollbar functionality
class HorizontalScrollBarDecorator extends WindowDecorator {
public HorizontalScrollBarDecorator (Window decoratedWindow) {
super(decoratedWindow);
}
@Override
public void draw() {
super.draw();
drawHorizontalScrollBar();
}
private void drawHorizontalScrollBar() {
// draw the horizontal scrollbar
}
@Override
public String getDescription() {
return super.getDescription() + ", including horizontal scrollbars";
}
}
Here's a test program that creates a Window instance which is fully decorated (i.e., with vertical and horizontal scrollbars), and prints its description:
public class DecoratedWindowTest {
public static void main(String[] args) {
// create a decorated Window with horizontal and vertical scrollbars
Window decoratedWindow = new HorizontalScrollBarDecorator (
new VerticalScrollBarDecorator(new SimpleWindow()));
// print the Window's description
System.out.println(decoratedWindow.getDescription());
}
}
The output of this program is "simple window, including vertical scrollbars, including horizontal scrollbars". Notice how the getDescription method of the two decorators first retrieve the decorated Window's description and decorates it with a suffix.
Second Example (coffee making scenario)
The next Java example illustrates the use of decorators using coffee making scenario. In this example, the scenario only includes cost and ingredients.
// The abstract Coffee class defines the functionality of Coffee implemented by decorator
public abstract class Coffee {
public abstract double getCost(); // returns the cost of the coffee
public abstract String getIngredients(); // returns the ingredients of the coffee
}
// extension of a simple coffee without any extra ingredients
public class SimpleCoffee extends Coffee {
public double getCost() {
return 1;
}
public String getIngredients() {
return "Coffee";
}
}
The following classes contain the decorators for all Coffee classes, including the decorator classes themselves..
// abstract decorator class - note that it extends Coffee abstract class
public abstract class CoffeeDecorator extends Coffee {
protected final Coffee decoratedCoffee;
protected String ingredientSeparator = ", ";
public CoffeeDecorator(Coffee decoratedCoffee) {
this.decoratedCoffee = decoratedCoffee;
}
public double getCost() { // implementing methods of the abstract class
return decoratedCoffee.getCost();
}
public String getIngredients() {
return decoratedCoffee.getIngredients();
}
}
// Decorator Milk that mixes milk with coffee
// note it extends CoffeeDecorator
class Milk extends CoffeeDecorator {
public Milk(Coffee decoratedCoffee) {
super(decoratedCoffee);
}
public double getCost() { // overriding methods defined in the abstract superclass
return super.getCost() + 0.5;
}
public String getIngredients() {
return super.getIngredients() + ingredientSeparator + "Milk";
}
}
// Decorator Whip that mixes whip with coffee
// note it extends CoffeeDecorator
class Whip extends CoffeeDecorator {
public Whip(Coffee decoratedCoffee) {
super(decoratedCoffee);
}
public double getCost() {
return super.getCost() + 0.7;
}
public String getIngredients() {
return super.getIngredients() + ingredientSeparator + "Whip";
}
}
// Decorator Sprinkles that mixes sprinkles with coffee
// note it extends CoffeeDecorator
class Sprinkles extends CoffeeDecorator {
public Sprinkles(Coffee decoratedCoffee) {
super(decoratedCoffee);
}
public double getCost() {
return super.getCost() + 0.2;
}
public String getIngredients() {
return super.getIngredients() + ingredientSeparator + "Sprinkles";
}
}
Here's a test program that creates a Coffee instance which is fully decorated (i.e., with milk, whip, sprinkles), and calculate cost of coffee and prints its ingredients:
public class Main {
public static final void main(String[] args) {
Coffee c = new SimpleCoffee();
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
c = new Milk(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
c = new Sprinkles(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
c = new Whip(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
// Note that you can also stack more than one decorator of the same type
c = new Sprinkles(c);
System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients());
}
}
The output of this program is given below:
Cost: 1.0 Ingredient: Coffee
Cost: 1.5 Ingredient: Coffee, Milk
Cost: 1.7 Ingredient: Coffee, Milk, Sprinkles
Cost: 2.4 Ingredient: Coffee, Milk, Sprinkles, Whip
Window System
# the Window base class
class Window(object):
def draw(self, device):
device.append('flat window')
def info(self):
pass
# The decorator pattern approch
class WindowDecorator:
def __init__(self, w):
self.window = w
def draw(self, device):
self.window.draw(device)
def info(self):
self.window.info()
class BorderDecorator(WindowDecorator):
def draw(self, device):
self.window.draw(device)
device.append('borders')
class ScrollDecorator(WindowDecorator):
def draw(self, device):
self.window.draw(device)
device.append('scroll bars')
def test_deco():
# The way of using the decorator classes
w = ScrollDecorator(BorderDecorator(Window()))
dev = []
w.draw(dev)
print dev
test_deco()
Difference between subclass method and decorator pattern
# The subclass approch
class BorderedWindow(Window):
def draw(self, device):
super(BorderedWindow, self).draw(device)
device.append('borders')
class ScrolledWindow(Window):
def draw(self, device):
super(ScrolledWindow, self).draw(device)
device.append('scroll bars')
# combine the functionalities using multiple inheritance.
class MyWindow(ScrolledWindow, BorderedWindow, Window):
pass
def test_muli():
w = MyWindow()
dev = []
w.draw(dev)
print dev
def test_muli2():
# note that python can create a class on the fly.
MyWindow = type('MyWindow', (ScrolledWindow, BorderedWindow, Window), {})
w = MyWindow()
dev = []
w.draw(dev)
print dev
test_muli()
test_muli2()
Coffee example
type Coffee() =
abstract member Cost : double
abstract member Ingredients: string list
default this.Cost = 1.0
default this.Ingredients = ["Coffee"]
type CoffeeDecorator(coffee: Coffee) =
inherit Coffee ()
override this.Cost = coffee.Cost
override this.Ingredients = coffee.Ingredients
type WithMilk(coffee: Coffee) =
inherit CoffeeDecorator(coffee)
override this.Cost = base.Cost + 0.5
override this.Ingredients = ["Milk"] |> List.append base.Ingredients
type WithSprinkles(coffee: Coffee) =
inherit CoffeeDecorator(coffee)
override this.Cost = base.Cost + 0.2
override this.Ingredients = ["Sprinkles"] |> List.append base.Ingredients
let print (coffee: Coffee) =
printfn "Cost: %.2f$; Ingredients: %A" coffee.Cost coffee.Ingredients
let withAddins = Coffee() |> WithMilk |> WithSprinkles
print withAddins
Dynamic languages
The decorator pattern can also be implemented in dynamic languages either with interfaces or with traditional OOP inheritance.
External links
Facade
[edit | edit source]
A Facade pattern hides the complexities of the system and provides an interface to the client from where the client can access the system. Dividing a system into subsystems helps reduce complexity. We need to minimize the communication and dependencies between subsystems. For this, we introduce a facade object that provides a single, simplified interface to the more general facilities of a subsystem.
Examples
The SCP
command is a shortcut for SSH commands. A remote file copy could be done writing several commands with an SSH connection but it can be done in one command with SCP
. So the SCP
command is a facade for the SSH commands. Although it may not be coded in the object programming paradigm, it is a good illustration of the design pattern.
Cost
This pattern is very easy and has not additional cost.
Creation
This pattern is very easy to create.
Maintenance
This pattern is very easy to maintain.
Removal
This pattern is very easy to remove too.
Advises
- Do not use this pattern to mask only three or four method calls.
Implementations
This is an abstract example of how a client ("you") interacts with a facade (the "computer") to a complex system (internal computer parts, like CPU and HardDrive).
/* Complex parts */
class CPU {
public void freeze() { ... }
public void jump(long position) { ... }
public void execute() { ... }
}
class Memory {
public void load(long position, byte[] data) { ... }
}
class HardDrive {
public byte[] read(long lba, int size) { ... }
}
/* Facade */
class Computer {
private CPU processor;
private Memory ram;
private HardDrive hd;
public Computer() {
this.processor = new CPU();
this.ram = new Memory();
this.hd = new HardDrive();
}
public void start() {
processor.freeze();
ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE));
processor.jump(BOOT_ADDRESS);
processor.execute();
}
}
/* Client */
class You {
public static void main(String[] args) {
Computer facade = new Computer();
facade.start();
}
}
using System;
namespace Facade
{
public class CPU
{
public void Freeze() { }
public void Jump(long addr) { }
public void Execute() { }
}
public class Memory
{
public void Load(long position, byte[] data) { }
}
public class HardDrive
{
public byte[] Read(long lba, int size) { return null; }
}
public class Computer
{
var cpu = new CPU();
var memory = new Memory();
var hardDrive = new HardDrive();
public void StartComputer()
{
cpu.Freeze();
memory.Load(0x22, hardDrive.Read(0x66, 0x99));
cpu.Jump(0x44);
cpu.Execute();
}
}
public class SomeClass
{
public static void Main(string[] args)
{
var facade = new Computer();
facade.StartComputer();
}
}
}
# Complex parts
class CPU
def freeze; puts 'CPU: freeze'; end
def jump(position); puts "CPU: jump to #{position}"; end
def execute; puts 'CPU: execute'; end
end
class Memory
def load(position, data)
puts "Memory: load #{data} at #{position}"
end
end
class HardDrive
def read(lba, size)
puts "HardDrive: read sector #{lba} (#{size} bytes)"
return 'hdd data'
end
end
# Facade
class Computer
BOOT_ADDRESS = 0
BOOT_SECTOR = 0
SECTOR_SIZE = 512
def initialize
@cpu = CPU.new
@memory = Memory.new
@hard_drive = HardDrive.new
end
def start_computer
@cpu.freeze
@memory.load(BOOT_ADDRESS, @hard_drive.read(BOOT_SECTOR, SECTOR_SIZE))
@cpu.jump(BOOT_ADDRESS)
@cpu.execute
end
end
# Client
facade = Computer.new
facade.start_computer
# Complex parts
class CPU:
def freeze(self): pass
def jump(self, position): pass
def execute(self): pass
class Memory:
def load(self, position, data): pass
class HardDrive:
def read(self, lba, size): pass
# Facade
class Computer:
def __init__(self):
self.cpu = CPU()
self.memory = Memory()
self.hard_drive = HardDrive()
def start_computer(self):
self.cpu.freeze()
self.memory.load(0, self.hard_drive.read(0, 1024))
self.cpu.jump(10)
self.cpu.execute()
# Client
if __name__ == '__main__':
facade = Computer()
facade.start_computer()
/* Complex parts */
class CPU
{
public function freeze() { /* ... */ }
public function jump( $position ) { /* ... */ }
public function execute() { /* ... */ }
}
class Memory
{
public function load( $position, $data ) { /* ... */ }
}
class HardDrive
{
public function read( $lba, $size ) { /* ... */ }
}
/* Facade */
class Computer
{
protected $cpu = null;
protected $memory = null;
protected $hardDrive = null;
public function __construct()
{
$this->cpu = new CPU();
$this->memory = new Memory();
$this->hardDrive = new HardDrive();
}
public function startComputer()
{
$this->cpu->freeze();
$this->memory->load( BOOT_ADDRESS, $this->hardDrive->read( BOOT_SECTOR, SECTOR_SIZE ) );
$this->cpu->jump( BOOT_ADDRESS );
$this->cpu->execute();
}
}
/* Client */
$facade = new Computer();
$facade->startComputer();
/* Complex parts */
var CPU = function () {};
CPU.prototype = {
freeze: function () {
console.log('CPU: freeze');
},
jump: function (position) {
console.log('CPU: jump to ' + position);
},
execute: function () {
console.log('CPU: execute');
}
};
var Memory = function () {};
Memory.prototype = {
load: function (position, data) {
console.log('Memory: load "' + data + '" at ' + position);
}
};
var HardDrive = function () {};
HardDrive.prototype = {
read: function (lba, size) {
console.log('HardDrive: read sector ' + lba + '(' + size + ' bytes)');
return 'hdd data';
}
};
/* Facade */
var Computer = function () {
var cpu, memory, hardDrive;
cpu = new CPU();
memory = new Memory();
hardDrive = new HardDrive();
var constant = function (name) {
var constants = {
BOOT_ADDRESS: 0,
BOOT_SECTOR: 0,
SECTOR_SIZE: 512
};
return constants[name];
};
this.startComputer = function () {
cpu.freeze();
memory.load(constant('BOOT_ADDRESS'), hardDrive.read(constant('BOOT_SECTOR'), constant('SECTOR_SIZE')));
cpu.jump(constant('BOOT_ADDRESS'));
cpu.execute();
}
};
/* Client */
var facade = new Computer();
facade.startComputer();
/* Complex Parts */
/* CPU.as */
package
{
public class CPU
{
public function freeze():void
{
trace("CPU::freeze");
}
public function jump(addr:Number):void
{
trace("CPU::jump to", String(addr));
}
public function execute():void
{
trace("CPU::execute");
}
}
}
/* Memory.as */
package
{
import flash.utils.ByteArray;
public class Memory
{
public function load(position:Number, data:ByteArray):void
{
trace("Memory::load position:", position, "data:", data);
}
}
}
/* HardDrive.as */
package
{
import flash.utils.ByteArray;
public class HardDrive
{
public function read(lba:Number, size:int):ByteArray
{
trace("HardDrive::read returning null");
return null;
}
}
}
/* The Facade */
/* Computer.as */
package
{
public class Computer
{
public static const BOOT_ADDRESS:Number = 0x22;
public static const BOOT_SECTOR:Number = 0x66;
public static const SECTOR_SIZE:int = 0x200;
private var _cpu:CPU;
private var _memory:Memory;
private var _hardDrive:HardDrive;
public function Computer()
{
_cpu = new CPU();
_memory = new Memory();
_hardDrive = new HardDrive();
}
public function startComputer():void
{
_cpu.freeze();
_memory.load(BOOT_ADDRESS, _hardDrive.read(BOOT_SECTOR, SECTOR_SIZE));
_cpu.jump(BOOT_ADDRESS);
_cpu.execute();
}
}
}
/* Client.as : This is the application's Document class */
package
{
import flash.display.MovieClip;
public class Client extends MovieClip
{
private var _computer:Computer;
public function Client()
{
_computer = new Computer();
_computer.startComputer();
}
}
}
/* Complex parts */
package intel {
class CPU {
def freeze() = ???
def jump(position: Long) = ???
def execute() = ???
}
}
package ram.plain {
class Memory {
def load(position: Long, data: Array[Byte]) = ???
}
}
package hdd {
class HardDrive {
def read(lba: Long, size: Int): Array[Byte] = ???
}
}
/* Facade */
//imports for the facade
import common.patterns.intel.CPU
import common.patterns.ram.plain.Memory
import common.patterns.hdd.HardDrive
package pk {
class ComputerFacade(conf: String) {
val processor: CPU = new CPU
val ram: Memory = new Memory
val hd: HardDrive = new HardDrive
val BOOT_ADDRESS: Long = ???
val BOOT_SECTOR: Long = ???
val SECTOR_SIZE: Int = ???
def start() = {
processor.freeze()
ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE))
processor.jump(BOOT_ADDRESS)
processor.execute()
}
}
}
//imports for your package
import common.patterns.pk.ComputerFacade
/* Client */
object You {
def main(args: Array[String]) {
new ComputerFacade("conf").start()
}
}
program Facade;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
(* complex parts - > Subsystem *)
TCPU = class
procedure Freeze;
procedure Jump(position: Integer);
procedure Execute;
end;
TMemory = class
procedure Load(position: Integer; data: string);
end;
THardDrive = class
function Read(lba, size: Integer): string;
end;
(* Facade *)
TComputer = class
fCPU: TCPU;
fMemory: TMemory;
fHardDrive: THardDrive;
const
BOOT_ADDRESS: Integer = 0;
BOOT_SECTOR: Integer = 0;
SECTOR_SIZE: Integer = 512;
public
procedure Start_Computer;
constructor Create;
end;
{ TCPU }
procedure TCPU.Execute;
begin
WriteLn('CPU: execute');
end;
procedure TCPU.Freeze;
begin
WriteLn('CPU: freese');
end;
procedure TCPU.Jump(position: Integer);
begin
WriteLn('CPU: jump to ' + IntToStr(position));
end;
{ TMemory }
procedure TMemory.Load(position: Integer; data: string);
begin
WriteLn('Memory: load "' + data + '" at ' + IntToStr(position));
end;
{ THardDrive }
function THardDrive.Read(lba, size: Integer): string;
begin
WriteLn('HardDrive: read sector ' + IntToStr(lba) + ' (' + IntToStr(size) +
' bytes)');
Result := 'hdd data';
end;
{ TComputer }
constructor TComputer.Create;
begin
fCPU := TCPU.Create;
fMemory := TMemory.Create;
fHardDrive := THardDrive.Create;
end;
procedure TComputer.Start_Computer;
begin
fCPU.Freeze;
fMemory.Load(BOOT_ADDRESS, fHardDrive.Read(BOOT_SECTOR, SECTOR_SIZE));
fCPU.Jump(BOOT_ADDRESS);
fCPU.Execute;
end;
var
facad: TComputer;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
facad := TComputer.Create;
facad.Start_Computer;
WriteLn(#13#10 + 'Press any key to continue...');
ReadLn;
facad.Free;
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
end.
Factory method
[edit | edit source]
The factory pattern is a design pattern used to promote encapsulation of data representation.
- Problem
- We want to decide at run time what object is to be created based on some configuration or application parameter. When we write the code we do not know what class should be instantiated.
- Solution
- Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. Its primary purpose is to provide a way for users to retrieve an instance with a known compile-time type, but whose runtime type may actually be different. In other words, a factory method that is supposed to return an instance of the class Foo may return an instance of the class Foo, or it may return an instance of the class Bar, so long as Bar inherits from Foo. The reason for this is that it strengthens the boundary between implementor and client, hiding the true representation of the data (see Abstraction Barrier) from the user, thereby allowing the implementor to change this representation at anytime without affecting the client, as long as the client facing interface doesn't change.
Basic Implementation of the Factory Pattern
The general template for implementing the factory pattern is to provide a primary user facing class with static methods which the user can use to get instances with that type. Constructors are then made private/protected from the user, forcing them to use the static factory methods to get objects. The following Java code shows a very simple implementation of the factory pattern for type Foo.
public class Foo {
// Static factory method
public static Foo getInstance() {
// Inside this class, we have access to private methods
return new Foo();
}
// Guarded constructor, only accessible from within this class, since it's marked private
private Foo() {
// Typical initialization code goes here
}
} // End class Foo
With this code, it would be impossible for a client of the code to use the new operator to get an instance of the class, as is traditionally done:
// Client code
Foo f = new Foo(); // Won't Work!
because the constructor is marked private. Instead, the client would have to use the factory method:
// Client code
Foo f = Foo.getInstance(); // Works!
It should be noted that even within a programming language community, there is no general consensus as to the naming convention of a factory method. Some suggest naming the method with the name of the class, similar to a normal constructor, but starting with a lowercase. Others say that this is confusing, and suggest using an accessor type syntax, like the getInstance style used above, though others complain that this may incorrectly imply a singleton implementation. Likewise, some offer newInstance, but this is criticized as being misleading in certain situations where a strictly new instance may not actually be returned (once again, refer to the singleton pattern). As such, we will not attempt to follow any particularly rigid standard here, we will simply try to use a name that makes the most sense for our current purposes.
Factory Pattern Implementation of the Alphabet
That's great, you know how to implement a real simple factory pattern, but what good did it do you? Users are asking for something that fits into type Foo, and they're getting an instance of the class Foo, how is that different from just calling the constructor? Well it's not, except that you're putting another function call on the stack (which is a bad thing). But that's only for the above case. We'll now discuss a more useful use of the factory pattern. Consider a simple type called Letter, representing a letter in the alphabet, which has the following client facing interface (i.e., public instance methods):
char toCharacter();
boolean isVowel();
boolean isConsonant();
We could implement this easily enough without using the factory method, which might start out something like this:
public class Letter {
private char fTheLetter;
public Letter(char aTheLetter) {
fTheLetter = aTheLetter;
}
public char toCharacter() {
return fTheLetter;
}
public boolean isVowel() {
//TODO: we haven't implemented this yet
return true;
}
public boolean isConsonant() {
// TODO: we haven't implemented this yet
return false;
}
} // End class Letter
Fairly simple, but notice we haven't implemented the last two methods yet. We can still do it pretty easily. The first might look like this:
public boolean isVowel() {
return
fTheLetter == 'a' ||
fTheLetter == 'e' ||
fTheLetter == 'i' ||
fTheLetter == 'o' ||
fTheLetter == 'u' ||
fTheLetter == 'A' ||
fTheLetter == 'E' ||
fTheLetter == 'I' ||
fTheLetter == 'O' ||
fTheLetter == 'U';
}
Now that's not too bad, but we still need to do isConsonant. Fortunately, we at least know in this case that if it's a vowel, it's not a consonant, and vice versa, so our last method could simply be:
public boolean isConsonant() {
return !this.isVowel();
}
So what's the problem here? Basically, every time you call either of these methods, your program has to do all that checking. Granted, this isn't a real heavy burden for the Java Runtime Environment, but you can imagine a much more complex, much more time consuming operation. Wouldn't it be great if we could avoid doing this every time we call the method? Let's say, for instance, we could do it once when we create the object, and then not have to do it again. Well sure, we can do that. Here's an implementation that'll do that for us, and we still don't have to use the factory method:
public class Letter {
private char fTheLetter;
private boolean fIsVowel;
public Letter(char aTheLetter) {
fTheLetter = aTheLetter;
fIsVowel = fTheLetter == 'a' ||
fTheLetter == 'e' ||
fTheLetter == 'i' ||
fTheLetter == 'o' ||
fTheLetter == 'u' ||
fTheLetter == 'A' ||
fTheLetter == 'E' ||
fTheLetter == 'I' ||
fTheLetter == 'O' ||
fTheLetter == 'U';
}
public char toCharacter() {
return fTheLetter;
}
public boolean isVowel() {
return fIsVowel;
}
public boolean isConsonant() {
return !fIsVowel;
}
} // End class Letter
Notice how we moved the lengthy operation into the constructor, and stored the result. OK, so now we're all fine and dandy, no? Sure, but let's say you came up with a new idea, a different implementation: you want to split this type into two classes, one class to handle the vowels, and one to handle the consonants. Great, they can both be subclasses of the Letter class, and the user will never know the difference, right? Wrong. How is the client supposed to get at these new classes? They've got code that works perfectly well for them by calling new Letter('a') and new Letter('Z'). Now you're going to make them go through all their code and change these to new Vowel('a') and new Consonant('Z')? They probably won't be too happy with that. If only you could get new instances of both classes from one method! Well you can, just use a static method in the Letter class, it'll do the same one-time checking as the constructor did, and will return an appropriate instance of the right class. And what do you know, it's a factory method! But that still doesn't do your client much good, they still need to go through and change all the new Letter()s into Letter.getLetter(). Well, sad to say, it's too late to help them at all, unless you just give up your new implementation. But that illustrates the reason for using the factory method right off the bat. One of the key components of good object oriented programming is that you never know exactly where your code will go in the future. By making good use of the abstraction barrier and using encapsulation-friendly programming patterns, such as the factory pattern, you can better prepare yourself—and your client—for future changes to the specific implementation. In particular, it allows you to use a "big hammer" kind of approach to get something done in a perhaps-less-than-ideal but rapid manner in order to meet deadlines or move ahead with testing,. You can then go back later and refine the implementation—the data representation and algorithms—to be faster, smaller, or what-have-you, and as long as you maintained the abstraction barrier between implementor and client and properly encapsulated your implementation, then you can change it without requiring the client to change any of their code. Well now that I'm sure you're a raving advocate for the factory method, let's take a look at how we would implement it for our Letter type:
public abstract class Letter {
// Factory Method
public static Letter getLetter(char aTheLetter) {
// Like before, we do a one time check to see what kind of
// letter we are dealing with. Only this time, instead of setting
// a property to track it, we actually have a different class for each
// of the two letter types.
if (
aTheLetter == 'a' ||
aTheLetter == 'e' ||
aTheLetter == 'i' ||
aTheLetter == 'o' ||
aTheLetter == 'u' ||
aTheLetter == 'A' ||
aTheLetter == 'E' ||
aTheLetter == 'I' ||
aTheLetter == 'O' ||
aTheLetter == 'U'
) {
return new Vowel(aTheLetter);
} else {
return new Consonant(aTheLetter);
}
}
// User facing interface
// We make these methods abstract, thereby requiring all subclasses
// (actually, just all concrete subclasses, that is, non-abstract)
// to implement the methods.
public abstract boolean isVowel();
public abstract boolean isConsonant();
public abstract char getChar();
// Now we define the two concrete classes for this type,
// the ones that actually implement the type.
private static class Vowel extends Letter {
private char iTheLetter;
// Constructor
Vowel(char aTheLetter) {
this.iTheLetter = aTheLetter;
}
// Nice easy implementation of this method!
public boolean isVowel() {
return true;
}
// This one, too!
public boolean isConsonant() {
return false;
}
public char getLetter(){
return iTheLetter;
}
} // End local class Vowel
private static class Consonant extends Letter {
private char iTheLetter;
// Constructor
Consonant(char aTheLetter) {
this.iTheLetter = aTheLetter;
}
public boolean isVowel() {
return false;
}
public boolean isConsonant(){
return true;
}
public char getLetter(){
return iTheLetter;
}
} // End local class Consonant
} // End toplevel class Letter
Several things to note here.
- First, you'll notice the top level class Letter is abstract. This is fine because you'll notice that it doesn't actually do anything except define the interface and provide a top level container for the two other classes. However, it's also important (not just OK) to make this abstract because we don't want people trying to instantiate the Letter class directly. Of course we could solve this problem by making a private constructor, but making the class abstract instead is cleaner, and makes it more obvious that the Letter class is not meant to be instantiated. It also, as mentioned, allows us to define the user facing interface that the work horse classes need to implement.
- The two nested classes we created are called local classes, which is basically the same as an inner class except that local classes are static, and inner classes are not. They have to be static so that our static factory method can create them. If they were non static (i.e., dynamic) then they could only be accessed through an instance of the Letter class, which we can never have because Letter is abstract. Also note that (in Java, anyway) the fields for inner and local classes typically use the "i" (for inner) prefix, as opposed to the "f" (for field) prefix used by top level classes. This is simply a naming convention used by many Java programmers and doesn't actually effect the program.
- The two nested classes that implement the Letter data type do not actually have to be local/inner. They could just have easily been top level classes that extend the abstract Letter class. However, this is contrary to the point of the factory pattern, which is encapsulation. Top level classes can't be private in Java, because that doesn't make any sense (what are they private to?) and the whole point is that no client has to (or should, really) know how the type is implemented. Making these classes top level allows clients to potentially stumble across them, and worse yet, instantiate them, by-passing the factory pattern all together.
- Lastly, this is not very good code. There's a lot of ways we can make it better to really illustrate the power of the factory pattern. I'll discuss these refactorings briefly, and then show another, more polished, version of the above code which includes a lot of them.
Refactoring the Factory Pattern
Notice that both of the local classes do the same thing in a few places. This is redundant code which is not only more work to write, but it's also highly discouraged in object oriented programming (partially because it takes more work to write, but mostly because it's harder to maintain and prone to errors, e.g., you find a bug in the code and change it in one spot, but forget to in another.) Below is a list of redundancies in the above code:
- The field iTheLetter
- The method getLetter()
- The constructor of each inner class does the same thing.
In addition, as we discovered above, the isVowel() and isConsonant() just happen to always return the opposite of each other for a given instance. However, since this is something of a peculiarity for this particular example, we won't worry about it. The lesson you would learn from us doing that will already be covered in the refactoring of the getLetter() method. OK, so we have redundant code in two classes. If you're familiar with abstracting processes, then this is probably a familiar scenario to you. Often, having redundant code in two different classes makes them prime candidates for abstraction, meaning that a new abstract class is created to implement the redundant code, and the two classes simply extend this new abstract class instead of implementing the redundant code. Well what do you know? We already have an abstract super class that our redundant classes have in common. All we have to do is make the super class implement the redundant code, and the other classes will automatically inherit this implementation, as long as we don't override it. So that works fine for the getLetter() method, we can move both the method and the iTheLetter field up to the abstract parent class. But what about the constructors? Well our constructor takes an argument, so we won't automatically inherit it, that's just the way java works. But we can use the super keyword to automatically delegate to the super classes constructor. In other words, we'll implement the constructor in the super class, since that's where the field is anyway, and the other two classes will delegate to this method in their own constructors. For our example, this doesn't save much work, we're replacing a one line assignment with a one line call to super(), but in theory, there could be hundred of lines of code in the constructors, and moving it up could be a great help. At this point, you might be a little worried about putting a constructor in the Letter class. Didn't I already say not to do that? I thought we didn't want people trying to instantiate Letter directly? Don't worry, the class is still abstract. Even if there's a concrete constructor, Java won't let you instantiate an abstract class, because it's abstract, it could have method that are accessible but undefined, and it wouldn't know what to do if such a method was invoked. So putting the constructor in is fine. After making the above refactorings, our code now looks like this:
public abstract class Letter {
// Factory Method
public static Letter getLetter(char aTheLetter){
if (
aTheLetter == 'a' ||
aTheLetter == 'e' ||
aTheLetter == 'i' ||
aTheLetter == 'o' ||
aTheLetter == 'u' ||
aTheLetter == 'A' ||
aTheLetter == 'E' ||
aTheLetter == 'I' ||
aTheLetter == 'O' ||
aTheLetter == 'U'
) {
return new Vowel(aTheLetter);
} else {
return new Consonant(aTheLetter);
}
}
// Our new abstracted field. We'll make it protected so that subclasses can see it,
// and we rename it from "i" to "f", following our naming convention.
protected char fTheLetter;
// Our new constructor. It can't actually be used to instantiate an instance
// of Letter, but our sub classes can invoke it with super
protected Letter(char aTheLetter) {
this.fTheLetter = aTheLetter;
}
// The new method we're abstracting up to remove redundant code in the sub classes
public char getChar() {
return this.fTheLetter;
}
// Same old abstract methods that define part of our client facing interface
public abstract boolean isVowel();
public abstract boolean isConsonant();
// The local subclasses with the redundant code moved up.
private static class Vowel extends Letter {
// Constructor delegates to the super constructor
Vowel(char aTheLetter) {
super(aTheLetter);
}
// Still need to implement the abstract methods
public boolean isVowel() {
return true;
}
public boolean isConsonant(){
return false;
}
} // End local class Vowel
private static class Consonant extends Letter {
Consonant(char aTheLetter){
super(aTheLetter);
}
public boolean isVowel(){
return false;
}
public boolean isConsonant(){
return true;
}
} // End local class Consonant
} // End toplevel class Letter
Note that we made our abstracted field protected. This isn't strictly necessary in this case, we could have left it private, because the subclasses don't actually need to access it at all. In general, I prefer to make things protected instead of private, since, as I mentioned, you can never really be sure where a project will go in the future, and you may not want to restrict future implementors (including yourself) unnecessarily. However, many people prefer to default to private and only use protected when they know it's necessary. A major reason for this is the rather peculiar and somewhat unexpected meaning of protected in Java, which allows not only subclasses, but anything in the same package to access it. This is a bit of a digression, but I think it's a fairly important debate that a good Java programmer should be aware of.
The Factory Pattern and Parametric Polymorphism
The version of the Java Virtual Machine 5.0 has introduced something called Parametric Polymorphism, which goes by many other names in other languages, including "generic typing" in C++. In order to really understand the rest of this section, you should read that section first. But basically, this means that you can introduce additional parameters into a class—parameters which are set at instantiation—that define the types of certain elements in the class, for instance fields or method return values. This is a very powerful tool which allows programmers to avoid a lot of those nasty instanceofs and narrowing castes. However, the implementation of this device in the JVM does not promote the use of the Factory pattern, and in the two do not play well together. This is because Java does not allow methods to be parameterized the way types are, so you cannot dynamically parameterize an instance through a method, only through use of the new operator. As an example, imagine a type Foo which is parameterized with a single type which we'll call T. In java we would write this class like this:
class Foo<T> {
} // End class Foo
Now we can have instances of Foo parameterized by all sorts of types, for instance:
Foo<String> fooOverString = new Foo<String>();
Foo<Integer> fooOverInteger = new Foo<Integer>();
But let's say we want to use the factory pattern for Foo. How do we do that? You could create a different factory method for each type you want to parameterize over, for instance:
class Foo<T> {
static Foo<String> getFooOverString() {
return new Foo<String>();
}
static Foo<Integer> getFooOverInteger() {
return new Foo<Integer>();
}
} // End class Foo
But what about something like the ArrayList class (in the java.util package)? In the java standard libraries released with 5.0, ArrayList is parameterized to define the type of the object stored in it. We certainly don't want to restrict what kinds of types it can be parameterized with by having to write a factory method for each type. This is often the case with parameterized types: you don't know what types users will want to parameterize with, and you don't want to restrict them, so the factory pattern won't work for that. You are allowed to instantiate a parameterized type in a generic form, meaning you don't specify the parameter at all, you just instantiate it the way you would have before 5.0. But that forces you to give up the parameterization. This is how you do it with generics:
class Foo<T> {
public static <E> Foo<E> getFoo() {
return new Foo<E>();
}
} // End class Foo
Examples
In Java, a class that implements java.sql.Connection
is a factory of statements. By calling the createStatement()
method, you create a statement for which you only know the interface. The factory chooses the right instance class for you.
Cost
This pattern is not so expensive when it is implemented at the right time. It can be more expensive if you have to refactor an existing code.
Creation
Its implementation is easy and there is no additional cost (it is not more expensive than an implementation without this pattern).
Maintenance
There is no additional cost nor additional constraint.
Removal
This pattern can be easily removed as automatic refactoring operations can easily remove its existence.
Good practices
- Name the factory class with the instanciated class in prefix and the factory term in suffix, to indicate the use of the pattern to the other developers.
- Avoid to persist the factory result (in database) into the factory class, to respect the SOLID principles and allow the creation of ephemeral objects, for example into the automatic tests.
Implementation
REPORT zz_pizza_factory_test NO STANDARD PAGE HEADING .
TYPES ty_pizza_type TYPE i .
*----------------------------------------------------------------------*
* CLASS lcl_pizza DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_pizza DEFINITION ABSTRACT .
PUBLIC SECTION .
DATA p_pizza_name TYPE string .
METHODS get_price ABSTRACT
RETURNING value(y_price) TYPE i .
ENDCLASS . "lcl_pizza DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_ham_and_mushroom_pizza DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_ham_and_mushroom_pizza DEFINITION INHERITING FROM lcl_pizza .
PUBLIC SECTION .
METHODS constructor .
METHODS get_price REDEFINITION .
ENDCLASS . "lcl_ham_and_mushroom_pizza DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_deluxe_pizza DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_deluxe_pizza DEFINITION INHERITING FROM lcl_pizza .
PUBLIC SECTION .
METHODS constructor .
METHODS get_price REDEFINITION .
ENDCLASS . "lcl_ham_and_mushroom_pizza DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_hawaiian_pizza DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_hawaiian_pizza DEFINITION INHERITING FROM lcl_pizza .
PUBLIC SECTION .
METHODS constructor .
METHODS get_price REDEFINITION .
ENDCLASS . "lcl_ham_and_mushroom_pizza DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_pizza_factory DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_pizza_factory DEFINITION .
PUBLIC SECTION .
CONSTANTS: BEGIN OF co_pizza_type ,
ham_mushroom TYPE ty_pizza_type VALUE 1 ,
deluxe TYPE ty_pizza_type VALUE 2 ,
hawaiian TYPE ty_pizza_type VALUE 3 ,
END OF co_pizza_type .
CLASS-METHODS create_pizza IMPORTING x_pizza_type TYPE ty_pizza_type
RETURNING value(yo_pizza) TYPE REF TO lcl_pizza
EXCEPTIONS ex_invalid_pizza_type .
ENDCLASS . "lcl_pizza_factory DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_ham_and_mushroom_pizza
*----------------------------------------------------------------------*
CLASS lcl_ham_and_mushroom_pizza IMPLEMENTATION .
METHOD constructor .
super->constructor( ) .
p_pizza_name = 'Ham & Mushroom Pizza'(001) .
ENDMETHOD . "constructor
METHOD get_price .
y_price = 850 .
ENDMETHOD . "get_price
ENDCLASS . "lcl_ham_and_mushroom_pizza IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS lcl_deluxe_pizza IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_deluxe_pizza IMPLEMENTATION .
METHOD constructor .
super->constructor( ) .
p_pizza_name = 'Deluxe Pizza'(002) .
ENDMETHOD . "constructor
METHOD get_price .
y_price = 1050 .
ENDMETHOD . "get_price
ENDCLASS . "lcl_deluxe_pizza IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS lcl_hawaiian_pizza IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_hawaiian_pizza IMPLEMENTATION .
METHOD constructor .
super->constructor( ) .
p_pizza_name = 'Hawaiian Pizza'(003) .
ENDMETHOD . "constructor
METHOD get_price .
y_price = 1150 .
ENDMETHOD . "get_price
ENDCLASS . "lcl_hawaiian_pizza IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS lcl_pizza_factory IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_pizza_factory IMPLEMENTATION .
METHOD create_pizza .
CASE x_pizza_type .
WHEN co_pizza_type-ham_mushroom .
CREATE OBJECT yo_pizza TYPE lcl_ham_and_mushroom_pizza .
WHEN co_pizza_type-deluxe .
CREATE OBJECT yo_pizza TYPE lcl_deluxe_pizza .
WHEN co_pizza_type-hawaiian .
CREATE OBJECT yo_pizza TYPE lcl_hawaiian_pizza .
ENDCASE .
ENDMETHOD . "create_pizza
ENDCLASS . "lcl_pizza_factory IMPLEMENTATION
START-OF-SELECTION .
DATA go_pizza TYPE REF TO lcl_pizza .
DATA lv_price TYPE i .
DO 3 TIMES .
go_pizza = lcl_pizza_factory=>create_pizza( sy-index ) .
lv_price = go_pizza->get_price( ) .
WRITE:/ 'Price of', go_pizza->p_pizza_name, 'is £', lv_price LEFT-JUSTIFIED .
ENDDO .
*Output:
*Price of Ham & Mushroom Pizza is £ 850
*Price of Deluxe Pizza is £ 1.050
*Price of Hawaiian Pizza is £ 1.150
public class Pizza
{
protected var _price:Number;
public function get price():Number
{
return _price;
}
}
public class HamAndMushroomPizza extends Pizza
{
public function HamAndMushroomPizza()
{
_price = 8.5;
}
}
public class DeluxePizza extends Pizza
{
public function DeluxePizza()
{
_price = 10.5;
}
}
public class HawaiianPizza extends Pizza
{
public function HawaiianPizza()
{
_price = 11.5;
}
}
public class PizzaFactory
{
static public function createPizza(type:String):Pizza
{
switch (type)
{
case "HamAndMushroomPizza":
return new HamAndMushroomPizza();
break;
case "DeluxePizza":
return new DeluxePizza();
break;
case "HawaiianPizza":
return new HawaiianPizza();
break;
default:
throw new ArgumentError("The pizza type " + type + " is not recognized.");
}
}
}
public class Main extends Sprite
{
public function Main()
{
for each (var pizza:String in ["HamAndMushroomPizza", "DeluxePizza", "HawaiianPizza"])
{
trace("Price of " + pizza + " is " + PizzaFactory.createPizza(pizza).price);
}
}
}
Output:
Price of HamAndMushroomPizza is 8.5
Price of DeluxePizza is 10.5
Price of HawaiianPizza is 11.5
This C++11 implementation is based on the pre C++98 implementation in the book.
#include <iostream>
enum Direction {North, South, East, West};
class MapSite {
public:
virtual void enter() = 0;
virtual ~MapSite() = default;
};
class Room : public MapSite {
public:
Room() :roomNumber(0) {}
Room(int n) :roomNumber(n) {}
void setSide(Direction d, MapSite* ms) {
std::cout << "Room::setSide " << d << ' ' << ms << '\n';
}
virtual void enter() {}
Room(const Room&) = delete; // rule of three
Room& operator=(const Room&) = delete;
private:
int roomNumber;
};
class Wall : public MapSite {
public:
Wall() {}
virtual void enter() {}
};
class Door : public MapSite {
public:
Door(Room* r1 = nullptr, Room* r2 = nullptr)
:room1(r1), room2(r2) {}
virtual void enter() {}
Door(const Door&) = delete; // rule of three
Door& operator=(const Door&) = delete;
private:
Room* room1;
Room* room2;
};
class Maze {
public:
void addRoom(Room* r) {
std::cout << "Maze::addRoom " << r << '\n';
}
Room* roomNo(int) const {
return nullptr;
}
};
// If createMaze calls virtual functions instead of constructor calls to create the rooms, walls, and doors it requires, then you can change the classes that get instantiated by making a subclass of MazeGame and redefining those virtual functions. This approach is an example of the Factory Method (121) pattern.
class MazeGame {
public:
Maze* createMaze () {
Maze* aMaze = makeMaze();
Room* r1 = makeRoom(1);
Room* r2 = makeRoom(2);
Door* theDoor = makeDoor(r1, r2);
aMaze->addRoom(r1);
aMaze->addRoom(r2);
r1->setSide(North, makeWall());
r1->setSide(East, theDoor);
r1->setSide(South, makeWall());
r1->setSide(West, makeWall());
r2->setSide(North, makeWall());
r2->setSide(East, makeWall());
r2->setSide(South, makeWall());
r2->setSide(West, theDoor);
return aMaze;
}
// factory methods:
virtual Maze* makeMaze() const {
return new Maze;
}
virtual Room* makeRoom(int n) const {
return new Room(n);
}
virtual Wall* makeWall() const {
return new Wall;
}
virtual Door* makeDoor(Room* r1, Room* r2) const {
return new Door(r1, r2);
}
virtual ~MazeGame() = default;
};
int main() {
MazeGame game;
game.createMaze();
}
The program output is like:
Maze::addRoom 0xcaced0
Maze::addRoom 0xcacef0
Room::setSide 0 0xcad340
Room::setSide 2 0xcacf10
Room::setSide 1 0xcad360
Room::setSide 3 0xcad380
Room::setSide 0 0xcad3a0
Room::setSide 2 0xcad3c0
Room::setSide 1 0xcad3e0
Room::setSide 3 0xcacf10
In Common Lisp, factory methods are not really needed, because classes and class names are first class values.
(defclass pizza ()
((price :accessor price)))
(defclass ham-and-mushroom-pizza (pizza)
((price :initform 850)))
(defclass deluxe-pizza (pizza)
((price :initform 1050)))
(defclass hawaiian-pizza (pizza)
((price :initform 1150)))
(defparameter *pizza-types*
(list 'ham-and-mushroom-pizza
'deluxe-pizza
'hawaiian-pizza))
(loop for pizza-type in *pizza-types*
do (format t "~%Price of ~a is ~a"
pizza-type
(price (make-instance pizza-type))))
Output:
Price of HAM-AND-MUSHROOM-PIZZA is 850
Price of DELUXE-PIZZA is 1050
Price of HAWAIIAN-PIZZA is 1150
program FactoryMethod;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
// Product
TProduct = class(TObject)
public
function GetName(): string; virtual; abstract;
end;
// ConcreteProductA
TConcreteProductA = class(TProduct)
public
function GetName(): string; override;
end;
// ConcreteProductB
TConcreteProductB = class(TProduct)
public
function GetName(): string; override;
end;
// Creator
TCreator = class(TObject)
public
function FactoryMethod(): TProduct; virtual; abstract;
end;
// ConcreteCreatorA
TConcreteCreatorA = class(TCreator)
public
function FactoryMethod(): TProduct; override;
end;
// ConcreteCreatorB
TConcreteCreatorB = class(TCreator)
public
function FactoryMethod(): TProduct; override;
end;
{ ConcreteProductA }
function TConcreteProductA.GetName(): string;
begin
Result := 'ConcreteProductA';
end;
{ ConcreteProductB }
function TConcreteProductB.GetName(): string;
begin
Result := 'ConcreteProductB';
end;
{ ConcreteCreatorA }
function TConcreteCreatorA.FactoryMethod(): TProduct;
begin
Result := TConcreteProductA.Create();
end;
{ ConcreteCreatorB }
function TConcreteCreatorB.FactoryMethod(): TProduct;
begin
Result := TConcreteProductB.Create();
end;
const
Count = 2;
var
Creators: array[1..Count] of TCreator;
Product: TProduct;
I: Integer;
begin
// An array of creators
Creators[1] := TConcreteCreatorA.Create();
Creators[2] := TConcreteCreatorB.Create();
// Iterate over creators and create products
for I := 1 to Count do
begin
Product := Creators[I].FactoryMethod();
WriteLn(Product.GetName());
Product.Free();
end;
for I := 1 to Count do
Creators[I].Free();
ReadLn;
end.
Example with pizza
abstract class Pizza {
public abstract int getPrice(); // Count the cents
}
class HamAndMushroomPizza extends Pizza {
public int getPrice() {
return 850;
}
}
class DeluxePizza extends Pizza {
public int getPrice() {
return 1050;
}
}
class HawaiianPizza extends Pizza {
public int getPrice() {
return 1150;
}
}
class PizzaFactory {
public enum PizzaType {
HamMushroom,
Deluxe,
Hawaiian
}
public static Pizza createPizza(PizzaType pizzaType) {
switch (pizzaType) {
case HamMushroom:
return new HamAndMushroomPizza();
case Deluxe:
return new DeluxePizza();
case Hawaiian:
return new HawaiianPizza();
}
throw new IllegalArgumentException("The pizza type " + pizzaType + " is not recognized.");
}
}
class PizzaLover {
/**
* Create all available pizzas and print their prices
*/
public static void main (String args[]) {
for (PizzaFactory.PizzaType pizzaType : PizzaFactory.PizzaType.values()) {
System.out.println("Price of " + pizzaType + " is " + PizzaFactory.createPizza(pizzaType).getPrice());
}
}
}
Output:
Price of HamMushroom is 850 Price of Deluxe is 1050 Price of Hawaiian is 1150
Another example with image
- Abstract creator
- Interface to create the Product.
package mypkg;
import java.awt.image.BufferedImage;
import java.io.IOException;
/**
*
* @author xxx
*/
public interface PhotoReader {
public BufferedImage getImage() throws IOException;
}
- Concrete creator
- a class to create specific Product.
package mypkg;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
/**
*
* @author xxx
*/
public class JPEGReader implements PhotoReader {
ImageReader reader;
File jpegFile;
ImageInputStream iis;
public JPEGReader(String filePath) throws IOException {
jpegFile = new File(filePath);
iis = ImageIO.createImageInputStream(jpegFile);
Iterator readers = ImageIO.getImageReadersByFormatName("jpg");
reader = (ImageReader)readers.next();
this.reader.setInput(iis, true);
}
public BufferedImage getImage() throws IOException {
return reader.read(0);
}
- Factory class
- a class to return a specific concrete creator at runtime to create the product.
package mypkg;
import java.io.IOException;
/**
*
* @author xxx
*/
public class PhotoReaderFactory {
enum Mimi {
jpg, JPG, gif, GIF, bmp, BMP, png, PNG
};
public static PhotoReader getPhotoReader(String filePath) {
String suffix = getFileSuffix(filePath);
PhotoReader reader = null;
try {
switch (Mimi.valueOf(suffix)) {
case jpg :
case JPG : reader = new JPEGReader(filePath); break;
case gif :
case GIF : reader = new GIFReader(filePath); break;
case bmp :
case BMP : reader = new BMPReader(filePath); break;
case png :
case PNG : reader = new PNGReader(filePath); break;
default : break;
}
} catch(IOException io) {
io.printStackTrace();
}
return reader;
}
private static String getFileSuffix(String filePath) {
String[] stringArray = filePath.split("\\.");
return stringArray[stringArray.length - 1];
}
}
This example in JavaScript uses Firebug console to output information.
/**
* Extends parent class with child. In Javascript, the keyword "extends" is not
* currently implemented, so it must be emulated.
* Also it is not recommended to use keywords for future use, so we name this
* function "extends" with capital E. Javascript is case-sensitive.
*
* @param function parent constructor function
* @param function (optional) used to override default child constructor function
*/
function Extends(parent, childConstructor) {
var F = function () {};
F.prototype = parent.prototype;
var Child = childConstructor || function () {};
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.parent = parent.prototype;
// return instance of new object
return Child;
}
/**
* Abstract Pizza object constructor
*/
function Pizza() {
throw new Error('Cannot instatiate abstract object!');
}
Pizza.prototype.price = 0;
Pizza.prototype.getPrice = function () {
return this.price;
}
var HamAndMushroomPizza = Extends(Pizza);
HamAndMushroomPizza.prototype.price = 8.5;
var DeluxePizza = Extends(Pizza);
DeluxePizza.prototype.price = 10.5;
var HawaiianPizza = Extends(Pizza);
HawaiianPizza.prototype.price = 11.5;
var PizzaFactory = {
createPizza: function (type) {
var baseObject = 'Pizza';
var targetObject = type.charAt(0).toUpperCase() + type.substr(1);
if (typeof window[targetObject + baseObject] === 'function') {
return new window[targetObject + baseObject];
}
else {
throw new Error('The pizza type ' + type + ' is not recognized.');
}
}
};
//var price = PizzaFactory.createPizza('deluxe').getPrice();
var pizzas = ['HamAndMushroom', 'Deluxe', 'Hawaiian'];
for (var i in pizzas) {
console.log('Price of ' + pizzas[i] + ' is ' + PizzaFactory.createPizza(pizzas[i]).getPrice());
}
Output
Price of HamAndMushroom is 8.50 Price of Deluxe is 10.50 Price of Hawaiian is 11.50
class Pizza a where
price :: a -> Float
data HamMushroom = HamMushroom
data Deluxe = Deluxe
data Hawaiian = Hawaiian
instance Pizza HamMushroom where
price _ = 8.50
instance Pizza Deluxe where
price _ = 10.50
instance Pizza Hawaiian where
price _ = 11.50
Usage example:
main = print (price Hawaiian)
package Pizza;
use Moose;
has price => (is => "rw", isa => "Num", builder => "_build_price" );
package HamAndMushroomPizza;
use Moose; extends "Pizza";
sub _build_price { 8.5 }
package DeluxePizza;
use Moose; extends "Pizza";
sub _build_price { 10.5 }
package HawaiianPizza;
use Moose; extends "Pizza";
sub _build_price { 11.5 }
package PizzaFactory;
sub create {
my ( $self, $type ) = @_;
return ($type . "Pizza")->new;
}
package main;
for my $type ( qw( HamAndMushroom Deluxe Hawaiian ) ) {
printf "Price of %s is %.2f\n", $type, PizzaFactory->create( $type )->price;
}
Factories are not really needed for this example in Perl, and this may be written more concisely:
package Pizza;
use Moose;
has price => (is => "rw", isa => "Num", builder => "_build_price" );
package HamAndMushroomPizza;
use Moose; extends "Pizza";
sub _build_price { 8.5 }
package DeluxePizza;
use Moose; extends "Pizza";
sub _build_price { 10.5 }
package HawaiianPizza;
use Moose; extends "Pizza";
sub _build_price { 11.5 }
package main;
for my $type ( qw( HamAndMushroom Deluxe Hawaiian ) ) {
printf "Price of %s is %.2f\n", $type, ($type . "Pizza")->new->price;
}
Output
Price of HamAndMushroom is 8.50 Price of Deluxe is 10.50 Price of Hawaiian is 11.50
<?php
abstract class Pizza
{
protected $_price;
public function getPrice()
{
return $this->_price;
}
}
class HamAndMushroomPizza extends Pizza
{
protected $_price = 8.5;
}
class DeluxePizza extends Pizza
{
protected $_price = 10.5;
}
class HawaiianPizza extends Pizza
{
protected $_price = 11.5;
}
class PizzaFactory
{
public static function createPizza($type)
{
$baseClass = 'Pizza';
$targetClass = ucfirst($type).$baseClass;
if (class_exists($targetClass) && is_subclass_of($targetClass, $baseClass))
return new $targetClass;
else
throw new Exception("The pizza type '$type' is not recognized.");
}
}
$pizzas = array('HamAndMushroom','Deluxe','Hawaiian');
foreach($pizzas as $p) {
printf(
"Price of %s is %01.2f".PHP_EOL ,
$p ,
PizzaFactory::createPizza($p)->getPrice()
);
}
// Output:
// Price of HamAndMushroom is 8.50
// Price of Deluxe is 10.50
// Price of Hawaiian is 11.50
?>
#
# Pizza
#
class Pizza(object):
def __init__(self):
self._price = None
def get_price(self):
return self._price
class HamAndMushroomPizza(Pizza):
def __init__(self):
self._price = 8.5
class DeluxePizza(Pizza):
def __init__(self):
self._price = 10.5
class HawaiianPizza(Pizza):
def __init__(self):
self._price = 11.5
#
# PizzaFactory
#
class PizzaFactory(object):
@staticmethod
def create_pizza(pizza_type):
if pizza_type == 'HamMushroom':
return HamAndMushroomPizza()
elif pizza_type == 'Deluxe':
return DeluxePizza()
elif pizza_type == 'Hawaiian':
return HawaiianPizza()
if __name__ == '__main__':
for pizza_type in ('HamMushroom', 'Deluxe', 'Hawaiian'):
print 'Price of {0} is {1}'.format(pizza_type, PizzaFactory.create_pizza(pizza_type).get_price())
As in Perl, Common Lisp and other dynamic languages, factories of the above sort aren't really necessary, since classes are first-class objects and can be passed around directly, leading to this more natural version:
#
# Pizza
#
class Pizza(object):
def __init__(self):
self._price = None
def get_price(self):
return self._price
class HamAndMushroomPizza(Pizza):
def __init__(self):
self._price = 8.5
class DeluxePizza(Pizza):
def __init__(self):
self._price = 10.5
class HawaiianPizza(Pizza):
def __init__(self):
self._price = 11.5
if __name__ == '__main__':
for pizza_class in (HamAndMushroomPizza, DeluxePizza, HawaiianPizza):
print('Price of {0} is {1}'.format(pizza_class.__name__, pizza_class().get_price()))
Note in the above that the classes themselves are simply used as values, which pizza_class iterates over. The class gets created simply by treating it as a function. In this case, if pizza_class holds a class, then pizza_class() creates a new object of that class. Another way of writing the final clause, which sticks more closely to the original example and uses strings instead of class objects, is as follows:
if __name__ == '__main__':
for pizza_type in ('HamAndMushroom', 'Deluxe', 'Hawaiian'):
print 'Price of {0} is {1}'.format(pizza_type, eval(pizza_type + 'Pizza')().get_price())
In this case, the correct class name is constructed as a string by adding 'Pizza', and eval is called to turn it into a class object.
Imports System
Namespace FactoryMethodPattern
Public Class Program
Shared Sub Main()
OutputPizzaFactory(New LousPizzaStore())
OutputPizzaFactory(New TonysPizzaStore())
Console.ReadKey()
End Sub
Private Shared Sub OutputPizzaFactory(ByVal factory As IPizzaFactory)
Console.WriteLine("Welcome to {0}", factory.Name)
For Each p As Pizza In factory.CreatePizzas
Console.WriteLine(" {0} - ${1} - {2}", p.GetType().Name, p.Price, p.Toppings)
Next
End Sub
End Class
Public MustInherit Class Pizza
Protected _toppings As String
Protected _price As Decimal
Public ReadOnly Property Toppings() As String
Get
Return _toppings
End Get
End Property
Public ReadOnly Property Price() As Decimal
Get
Return _price
End Get
End Property
Public Sub New(ByVal __price As Decimal)
_price = __price
End Sub
End Class
Public Interface IPizzaFactory
ReadOnly Property Name() As String
Function CreatePizzas() As Pizza()
End Interface
Public Class Pepperoni
Inherits Pizza
Public Sub New(ByVal price As Decimal)
MyBase.New(price)
_toppings = "Cheese, Pepperoni"
End Sub
End Class
Public Class Cheese
Inherits Pizza
Public Sub New(ByVal price As Decimal)
MyBase.New(price)
_toppings = "Cheese"
End Sub
End Class
Public Class LousSpecial
Inherits Pizza
Public Sub New(ByVal price As Decimal)
MyBase.New(price)
_toppings = "Cheese, Pepperoni, Ham, Lou's Special Sauce"
End Sub
End Class
Public Class TonysSpecial
Inherits Pizza
Public Sub New(ByVal price As Decimal)
MyBase.New(price)
_toppings = "Cheese, Bacon, Tomatoes, Tony's Special Sauce"
End Sub
End Class
Public Class LousPizzaStore
Implements IPizzaFactory
Public Function CreatePizzas() As Pizza() Implements IPizzaFactory.CreatePizzas
Return New Pizza() {New Pepperoni(6.99D), New Cheese(5.99D), New LousSpecial(7.99D)}
End Function
Public ReadOnly Property Name() As String Implements IPizzaFactory.Name
Get
Return "Lou's Pizza Store"
End Get
End Property
End Class
Public Class TonysPizzaStore
Implements IPizzaFactory
Public Function CreatePizzas() As Pizza() Implements IPizzaFactory.CreatePizzas
Return New Pizza() {New Pepperoni(6.5D), New Cheese(5.5D), New TonysSpecial(7.5D)}
End Function
Public ReadOnly Property Name() As String Implements IPizzaFactory.Name
Get
Return "Tony's Pizza Store"
End Get
End Property
End Class
End Namespace
Output:
Welcome to Lou's Pizza Store
Pepperoni - $6.99 - Cheese, Pepperoni
Cheese - $5.99 - Cheese
LousSpecial - $7.99 - Cheese, Pepperoni, Ham, Lou's Special Sauce
Welcome to Tony's Pizza Store
Pepperoni - $6.5 - Cheese, Pepperoni
Cheese - $5.5 - Cheese
TonysSpecial - $7.5 - Cheese, Bacon, Tomatoes, Tony's Special Sauce
Flyweight
[edit | edit source]
It is a mechanism by which you can avoid creating a large number of object instances to represent the entire system. To decide if some part of a program is a candidate for using Flyweights, consider whether it is possible to remove some data from the class and make it extrinsic.
Examples
A classic example usage of the flyweight pattern is the data structures for graphical representation of characters in a word processor. It might be desirable to have, for each character in a document, a glyph object containing its font outline, font metrics, and other formatting data, but this would amount to hundreds or thousands of bytes for each character. Instead, for every character there might be a reference to a flyweight glyph object shared by every instance of the same character in the document; only the position of each character (in the document and/or the page) would need to be stored internally. Another example is string interning.
In video games, it is usual that you have to display the same sprite (i.e. an image of an item of the game) several times. It would highly use the CPU and the memory if each sprite was a different object. So the sprite is created once and then is rendered at different locations in the screen. This problem can be solved using the flyweight pattern. The object that renders the sprite is a flyweight.
Cost
There are several implementations for this pattern. So it's up to you to find a cheap implementation. Only implement this pattern if you have or will have CPU or memory issues.
Creation
This pattern is quite easy to create.
Maintenance
This pattern is quite easy to maintain.
Removal
This pattern is quite easy to remove too.
Advises
- Use pre-existing tools from the language like the sets in Java.
Implementations
The following programs illustrate the document example given above: the flyweights are called FontData in the Java example. The examples illustrate the flyweight pattern used to reduce memory by loading only the data necessary to perform some immediate task from a large Font object into a much smaller FontData (flyweight) object.
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import java.awt.Color;
public final class FontData {
enum FontEffect {
BOLD, ITALIC, SUPERSCRIPT, SUBSCRIPT, STRIKETHROUGH
}
/**
* A weak hash map will drop unused references to FontData.
* Values have to be wrapped in WeakReferences,
* because value objects in weak hash map are held by strong references.
*/
private static final WeakHashMap<FontData, WeakReference<FontData>> FLY_WEIGHT_DATA =
new WeakHashMap<FontData, WeakReference<FontData>>();
private final int pointSize;
private final String fontFace;
private final Color color;
private final Set<FontEffect> effects;
private FontData(int pointSize, String fontFace, Color color, EnumSet<FontEffect> effects) {
this.pointSize = pointSize;
this.fontFace = fontFace;
this.color = color;
this.effects = Collections.unmodifiableSet(effects);
}
public static FontData create(int pointSize, String fontFace, Color color,
FontEffect... effects) {
EnumSet<FontEffect> effectsSet = EnumSet.noneOf(FontEffect.class);
for (FontEffect fontEffect : effects) {
effectsSet.add(fontEffect);
}
// We are unconcerned with object creation cost, we are reducing overall memory consumption
FontData data = new FontData(pointSize, fontFace, color, effectsSet);
FontData result = null;
// Retrieve previously created instance with the given values if it (still) exists
WeakReference<FontData> ref = FLY_WEIGHT_DATA.get(data);
if (ref != null) {
result = ref.get();
}
// Store new font data instance if no matching instance exists
if(result == null){
FLY_WEIGHT_DATA.put(data, new WeakReference<FontData> (data));
result = data;
}
// return the single immutable copy with the given values
return result;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof FontData) {
if (obj == this) {
return true;
}
FontData other = (FontData) obj;
return other.pointSize == pointSize && other.fontFace.equals(fontFace)
&& other.color.equals(color) && other.effects.equals(effects);
}
return false;
}
@Override
public int hashCode() {
return (pointSize * 37 + effects.hashCode() * 13) * fontFace.hashCode();
}
// Getters for the font data, but no setters. FontData is immutable.
}
'''http://codesnipers.com/?q=python-flyweights'''
from __future__ import print_function
import weakref
class Card(object):
# comment __new__ and uncomment __init__ to see the difference
'''The object pool. Has builtin reference counting'''
_CardPool = weakref.WeakValueDictionary()
'''If the object exists in the pool just return it (instead of creating a new one)'''
def __new__(cls, value, suit):
obj = Card._CardPool.get(value + suit, None)
if not obj:
obj = object.__new__(cls)
Card._CardPool[value + suit] = obj
obj.value, obj.suit = value, suit
return obj
# def __init__(self, value, suit):
# self.value, self.suit = value, suit
def __repr__(self):
return "<Card: %s%s>" % (self.value, self.suit)
if __name__ == '__main__':
c1 = Card('9', 'h')
c2 = Card('9', 'h')
print(c1, c2)
print(c1 == c2)
print(id(c1), id(c2))
Interpreter
[edit | edit source]
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
Examples
The following Reverse Polish notation example illustrates the interpreter pattern. The grammar:
expression ::= plus | minus | variable | number
defines a language which contains reverse Polish expressions like:
plus ::= expression expression '+'
minus ::= expression expression '-'
variable ::= 'a' | 'b' | 'c' | ... | 'z'
digit ::= '0' | '1' | ... '9'
number ::= digit | digit number
a b +
Following the interpreter pattern there is a class for each grammar rule.
a b c + -
a b + c a - -
Cost
This pattern is not expensive. It dramatically reduces the business code so there is only few code to handle.
Creation
If the code already exists, this pattern is a little expensive.
Maintenance
This pattern is very easy to maintain. There is no additional cost due to the pattern.
Removal
This pattern is easy to remove with refactoring operations from your IDE.
Advises
- Use the
Interpreter
term to indicate the use of the pattern to the other developers.
Implementations
The following Backus–Naur form example illustrates the interpreter pattern. The grammar
expression ::= plus | minus | variable | number
plus ::= expression expression '+'
minus ::= expression expression '-'
variable ::= 'a' | 'b' | 'c' | ... | 'z'
digit = '0' | '1' | ... | '9'
number ::= digit | digit number
defines a language that contains Reverse Polish Notation expressions like:
a b + a b c + - a b + c a - -
This structural code demonstrates the Interpreter patterns, which using a defined grammar, provides the interpreter that processes parsed statements.
using System;
using System.Collections.Generic;
namespace OOP;
class Program
{
static void Main()
{
var context = new Context();
var input = new MyExpression();
var expression = new OrExpression
{
Left = new EqualsExpression
{
Left = input,
Right = new MyExpression { Value = "4" }
},
Right = new EqualsExpression
{
Left = input,
Right = new MyExpression { Value = "four" }
}
};
input.Value = "four";
expression.Interpret(context);
// Output: "true"
Console.WriteLine(context.Result.Pop());
input.Value = "44";
expression.Interpret(context);
// Output: "false"
Console.WriteLine(context.Result.Pop());
}
}
class Context
{
public Stack<string> Result = new Stack<string>();
}
interface IExpression
{
void Interpret(Context context);
}
abstract class OperatorExpression : IExpression
{
public IExpression Left { private get; set; }
public IExpression Right { private get; set; }
public void Interpret(Context context)
{
Left.Interpret(context);
string leftValue = context.Result.Pop();
Right.Interpret(context);
string rightValue = context.Result.Pop();
DoInterpret(context, leftValue, rightValue);
}
protected abstract void DoInterpret(Context context, string leftValue, string rightValue);
}
class EqualsExpression : OperatorExpression
{
protected override void DoInterpret(Context context, string leftValue, string rightValue)
{
context.Result.Push(leftValue == rightValue ? "true" : "false");
}
}
class OrExpression : OperatorExpression
{
protected override void DoInterpret(Context context, string leftValue, string rightValue)
{
context.Result.Push(leftValue == "true" || rightValue == "true" ? "true" : "false");
}
}
class MyExpression : IExpression
{
public string Value { private get; set; }
public void Interpret(Context context)
{
context.Result.Push(Value);
}
}
Another example:
using System;
using System.Collections.Generic;
namespace Interpreter
{
class Program
{
interface IExpression
{
int Interpret(Dictionary<string, int> variables);
}
class Number : IExpression
{
public int number;
public Number(int number) { this.number = number; }
public int Interpret(Dictionary<string, int> variables) { return number; }
}
abstract class BasicOperation : IExpression
{
IExpression leftOperator, rightOperator;
public BasicOperation(IExpression left, IExpression right)
{
leftOperator = left;
rightOperator = right;
}
public int Interpret(Dictionary<string, int> variables)
{
return Execute(leftOperator.Interpret(variables), rightOperator.Interpret(variables));
}
abstract protected int Execute(int left, int right);
}
class Plus : BasicOperation
{
public Plus(IExpression left, IExpression right) : base(left, right) { }
protected override int Execute(int left, int right)
{
return left + right;
}
}
class Minus : BasicOperation
{
public Minus(IExpression left, IExpression right) : base(left, right) { }
protected override int Execute(int left, int right)
{
return left - right;
}
}
class Variable : IExpression
{
private string name;
public Variable(string name) { this.name = name; }
public int Interpret(Dictionary<string, int> variables)
{
return variables[name];
}
}
class Evaluator
{
private IExpression syntaxTree;
public Evaluator(string expression)
{
Stack<IExpression> stack = new Stack<IExpression>();
foreach (string token in expression.Split(' '))
{
if (token.Equals("+"))
stack.Push(new Plus(stack.Pop(), stack.Pop()));
else if (token.Equals("-")){
IExpression right = stack.Pop();
IExpression left = stack.Pop();
stack.Push(new Minus(left, right));
}else
stack.Push(new Variable(token));
}
syntaxTree = stack.Pop();
}
public int Evaluate(Dictionary<string, int> context)
{
return syntaxTree.Interpret(context);
}
}
static void Main(string[] args)
{
Evaluator evaluator = new Evaluator("w x z - +");
Dictionary<string, int> values = new Dictionary<string,int>();
values.Add("w", 5);
values.Add("x", 10);
values.Add("z", 42);
Console.WriteLine(evaluator.Evaluate(values));
}
}
}
public class Interpreter {
@FunctionalInterface
public interface Expr {
int interpret(Map<String, Integer> context);
static Expr number(int number) {
return context -> number;
}
static Expr plus(Expr left, Expr right) {
return context -> left.interpret(context) + right.interpret(context);
}
static Expr minus(Expr left, Expr right) {
return context -> left.interpret(context) - right.interpret(context);
}
static Expr variable(String name) {
return context -> context.getOrDefault(name, 0);
}
}
}
While the interpreter pattern does not address parsing, a parser is provided for completeness.
private static Expr parseToken(String token, ArrayDeque<Expr> stack) {
Expr left, right;
switch(token) {
case "+":
// It's necessary to remove first the right operand from the stack
right = stack.pop();
// ...and then the left one
left = stack.pop();
return Expr.plus(left, right);
case "-":
right = stack.pop();
left = stack.pop();
return Expr.minus(left, right);
default:
return Expr.variable(token);
}
}
public static Expr parse(String expression) {
ArrayDeque<Expr> stack = new ArrayDeque<Expr>();
for (String token : expression.split(" ")) {
stack.push(parseToken(token, stack));
}
return stack.pop();
}
Finally evaluating the expression "w x z - +" with w = 5, x = 10, and z = 42.
public static void main(final String[] args) {
Expr expr = parse("w x z - +");
Map<String, Integer> context = Map.of("w", 5, "x", 10, "z", 42);
int result = expr.interpret(context);
System.out.println(result); // -27
}
}
Another example:
import java.util.Map;
interface Expression {
public int interpret(Map<String, Expression> variables);
}
import java.util.Map;
class Number implements Expression {
private int number;
public Number(int number) {
this.number = number;
}
public int interpret(Map<String, Expression> variables) {
return number;
}
}
import java.util.Map;
class Plus implements Expression {
Expression leftOperand;
Expression rightOperand;
public Plus(Expression left, Expression right) {
leftOperand = left;
rightOperand = right;
}
public int interpret(Map<String, Expression> variables) {
return leftOperand.interpret(variables) + rightOperand.interpret(variables);
}
}
import java.util.Map;
class Minus implements Expression {
Expression leftOperand;
Expression rightOperand;
public Minus(Expression left, Expression right) {
leftOperand = left;
rightOperand = right;
}
public int interpret(Map<String, Expression> variables) {
return leftOperand.interpret(variables) - rightOperand.interpret(variables);
}
}
import java.util.Map;
class Variable implements Expression {
private String name;
public Variable(String name) {
this.name = name;
}
public int interpret(Map<String, Expression> variables) {
if (variables.get(name) == null) {
// Either return new Number(0).
return 0;
} else {
return variables.get(name).interpret(variables);
}
}
}
While the interpreter pattern does not address parsing a parser is provided for completeness.
import java.util.Map;
import java.util.Stack;
class Evaluator implements Expression {
private Expression syntaxTree;
public Evaluator(String expression) {
Stack<Expression> expressionStack = new Stack<Expression>();
for (String token : expression.split(" ")) {
if (token.equals("+")) {
Expression subExpression = new Plus(expressionStack.pop(), expressionStack.pop());
expressionStack.push( subExpression );
}
else if (token.equals("-")) {
// it's necessary remove first the right operand from the stack
Expression right = expressionStack.pop();
// ..and after the left one
Expression left = expressionStack.pop();
Expression subExpression = new Minus(left, right);
expressionStack.push( subExpression );
}
else
expressionStack.push( new Variable(token) );
}
syntaxTree = expressionStack.pop();
}
public int interpret(Map<String,Expression> context) {
return syntaxTree.interpret(context);
}
}
Finally evaluating the expression "w x z - +" with w = 5, x = 10, and z = 42.
import java.util.Map;
import java.util.HashMap;
public class InterpreterExample {
public static void main(String[] args) {
String expression = "w x z - +";
Evaluator sentence = new Evaluator(expression);
Map<String,Expression> variables = new HashMap<String,Expression>();
variables.put("w", new Number(5));
variables.put("x", new Number(10));
variables.put("z", new Number(42));
int result = sentence.interpret(variables);
System.out.println(result);
}
}
As JavaScript is dynamically typed, we do not implement an interface.
// Nonterminal expression
class Plus {
a;
b;
constructor(a, b) {
this.a = a;
this.b = b;
}
interpret(context) {
return this.a.interpret(context) + this.b.interpret(context);
}
}
// Nonterminal expression
class Minus {
a;
b;
constructor(a, b) {
this.a = a;
this.b = b;
}
interpret(context) {
return this.a.interpret(context) - this.b.interpret(context);
}
}
// Nonterminal expression
class Times {
a;
b;
constructor(a, b) {
this.a = a;
this.b = b;
}
interpret(context) {
return this.a.interpret(context) * this.b.interpret(context);
}
}
// Nonterminal expression
class Divide {
a;
b;
constructor(a, b) {
this.a = a;
this.b = b;
}
interpret(context) {
return this.a.interpret(context) / this.b.interpret(context);
}
}
// Terminal expression
class Number {
a;
constructor(a, b) {
this.a = a;
}
interpret(context) {
return this.a;
}
}
// Terminal expression
class Variable {
a;
constructor(a) {
this.a = a;
}
interpret(context) {
return context[this.a] || 0;
}
}
// Client
class Parse {
context;
constructor(context) {
this.context = context;
}
parse(expression) {
let tokens = expression.split(" ");
let queue = [];
for (let token of tokens) {
switch (token) {
case "+":
var b = queue.pop();
var a = queue.pop();
var exp = new Plus(a, b);
queue.push(exp);
break;
case "/":
var b = queue.pop();
var a = queue.pop();
var exp = new Divide(a, b);
queue.push(exp);
break;
case "*":
var b = queue.pop();
var a = queue.pop();
var exp = new Times(a, b);
queue.push(exp);
break;
case "-":
var b = queue.pop();
var a = queue.pop();
var exp = new Minus(a, b);
queue.push(exp);
break;
default:
if (isNaN(token)) {
var exp = new Variable(token);
queue.push(exp);
} else {
var number = parseInt(token);
var exp = new Number(number);
queue.push(exp);
}
break;
}
}
let main = queue.pop();
return main.interpret(this.context);
}
}
var res = new Parse({v: 45}).parse("16 v * 76 22 - -");
console.log(res)
//666
Example 1:
/**
* AbstractExpression
*/
interface Expression
{
public function interpret(array $context): int;
}
/**
* TerminalExpression
*/
class TerminalExpression implements Expression
{
/** @var string */
private $name;
public function __construct(string $name)
{
$this->name = $name;
}
public function interpret(array $context): int
{
return intval($context[$this->name]);
}
}
/**
* NonTerminalExpression
*/
abstract class NonTerminalExpression implements Expression
{
/** @var Expression $left */
protected $left;
/** @var ?Expression $right */
protected $right;
public function __construct(Expression $left, ?Expression $right)
{
$this->left = $left;
$this->right = $right;
}
abstract public function interpret(array $context): int;
public function getRight()
{
return $this->right;
}
public function setRight($right): void
{
$this->right = $right;
}
}
/**
* NonTerminalExpression - PlusExpression
*/
class PlusExpression extends NonTerminalExpression
{
public function interpret(array $context): int
{
return intval($this->left->interpret($context) + $this->right->interpret($context));
}
}
/**
* NonTerminalExpression - MinusExpression
*/
class MinusExpression extends NonTerminalExpression
{
public function interpret(array $context): int
{
return intval($this->left->interpret($context) - $this->right->interpret($context));
}
}
/**
* Client
*/
class InterpreterClient
{
protected function parseList(array &$stack, array $list, int &$index)
{
/** @var string $token */
$token = $list[$index];
switch($token) {
case '-':
list($left, $right) = $this->fetchArguments($stack, $list, $index);
return new MinusExpression($left, $right);
case '+':
list($left, $right) = $this->fetchArguments($stack, $list, $index);
return new PlusExpression($left, $right);
default:
return new TerminalExpression($token);
}
}
protected function fetchArguments(array &$stack, array $list, int &$index): array
{
/** @var Expression $left */
$left = array_pop($stack);
/** @var Expression $right */
$right = array_pop($stack);
if ($right === null) {
++$index;
$this->parseListAndPush($stack, $list, $index);
$right = array_pop($stack);
}
return array($left, $right);
}
protected function parseListAndPush(array &$stack, array $list, int &$index)
{
array_push($stack, $this->parseList($stack, $list, $index));
}
protected function parse(string $data): Expression
{
$stack = [];
$list = explode(' ', $data);
for ($index=0; $index<count($list); $index++) {
$this->parseListAndPush($stack, $list, $index);
}
return array_pop($stack);
}
public function main()
{
$data = "u + v - w + z";
$expr = $this->parse($data);
$context = ['u' => 3, 'v' => 7, 'w' => 35, 'z' => 9];
$res = $expr->interpret($context);
echo "result: $res" . PHP_EOL;
}
}
// test.php
function loadClass($className)
{
require_once __DIR__ . "/$className.php";
}
spl_autoload_register('loadClass');
(new InterpreterClient())->main();
//result: -16
Example 2: Based on the example above with another realization of the client.
/**
* Client
*/
class InterpreterClient
{
public function parseToken(string $token, array &$stack): Expression
{
switch($token) {
case '-':
/** @var Expression $left */
$left = array_pop($stack);
/** @var Expression $right */
$right = array_pop($stack);
return new MinusExpression($left, $right);
case '+':
/** @var Expression $left */
$left = array_pop($stack);
/** @var Expression $right */
$right = array_pop($stack);
return new PlusExpression($left, $right);
default:
return new TerminalExpression($token);
}
}
public function parse(string $data): Expression
{
$unfinishedData = null;
$stack = [];
$list = explode(' ', $data);
foreach ($list as $token) {
$data = $this->parseToken($token, $stack);
if (
($unfinishedData instanceof NonTerminalExpression) &&
($data instanceof TerminalExpression)
) {
$unfinishedData->setRight($data);
array_push($stack, $unfinishedData);
$unfinishedData = null;
continue;
}
if ($data instanceof NonTerminalExpression) {
if ($data->getRight() === null) {
$unfinishedData = $data;
continue;
}
}
array_push($stack, $data);
}
return array_pop($stack);
}
public function main()
{
$data = "u + v - w + z";
$expr = $this->parse($data);
$context = ['u' => 3, 'v' => 7, 'w' => 35, 'z' => 9];
$res = $expr->interpret($context);
echo "result: $res" . PHP_EOL;
}
}
Example 3: In a file we have the classes and the interface, defining the logic of the program (and applying the Interpreter pattern). Now the expr.php file:
<?php
interface expression{
public function interpret (array $variables);
public function __toString();
}
class number implements expression{
private $number;
public function __construct($number){
$this->number = intval($number);
}
public function interpret(array $variables){
return $this->number;
}
public function __toString(){
return (string) $this->number;
}
}
class plus implements expression{
private $left_op;
private $right_op;
public function __construct(expression $left, expression $right){
$this->left_op = $left;
$this->right_op = $right;
}
public function interpret(array $variables){
return ($this->left_op->interpret($variables) + $this->right_op->interpret($variables));
}
public function __toString(){
return (string) ("Left op: {$this->left_op} + Right op: {$this->right_op}\n");
}
}
class minus implements expression{
private $left_op;
private $right_op;
public function __construct(expression $left, expression $right){
$this->left_op = $left;
$this->right_op = $right;
}
public function interpret(array $variables){
return ($this->left_op->interpret($variables) - $this->right_op->interpret($variables));
}
public function __toString(){
return (string) ("Left op: {$this->left_op} - Right op: {$this->right_op}\n");
}
}
class variable implements expression{
private $name;
public function __construct($name){
$this->name = $name;
}
public function interpret(array $variables){
if(!isset($variables[$this->name]))
return 0;
return $variables[$this->name]->interpret($variables);
}
public function __toString(){
return (string) $this->name;
}
}
?>
And the evaluate.php:
<?php
require_once('expr.php');
class evaluator implements expression{
private $syntaxTree;
public function __construct($expression){
$stack = array();
$tokens = explode(" ", $expression);
foreach($tokens as $token){
if($token == "+"){
$right = array_pop($stack);
$left = array_pop($stack);
array_push($stack, new plus($left, $right));
}
else if($token == "-"){
$right = array_pop($stack);
$left = array_pop($stack);
array_push($stack, new minus($left, $right));
}else if(is_numeric($token)){
array_push($stack, new number($token));
}else{
array_push($stack, new variable($token));
}
}
$this->syntaxTree = array_pop($stack);
}
public function interpret(array $context){
return $this->syntaxTree->interpret($context);
}
public function __toString(){
return "";
}
}
// main code
// works for it:
$expression = "5 10 42 - +";
// or for it:
//$expression = "w x z - +";
$variables = array();
$variables['w'] = new number("5");
$variables['x'] = new number("10");
$variables['z'] = new number("42");
print ("Evaluating expression {$expression}\n");
$sentence = new evaluator($expression);
$result = $sentence->interpret($variables);
print $result . "\n";
?>
And you can run on a terminal by typing php5 -f evaluator.php (or putting it on a web application).
Iterator
[edit | edit source]
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
Examples
In Java, the interface java.util.Iterator<E>
is an implementation of the iterator pattern. That way, all the objects that implement the java.lang.Iterable<T>
interface don't need a handy implementation of this pattern.
Cost
This pattern has a cost. Only implement this pattern for an important amount of code. IDE refactoring can't help you much.
Creation
This pattern has a cost to create.
Maintenance
This pattern is easy to maintain.
Removal
This pattern has a cost to remove too.
Advises
- Put the iterator term in the name of the iterator class to indicate the use of the pattern to the other developers.
Implementations
Java has the Iterator interface.
A simple example showing how to return integers between [start, end] using an Iterator
import java.util.Iterator;
import java.util.NoSuchElementException;
public class RangeIteratorExample {
public static Iterator<Integer> range(int start, int end) {
return new Iterator<>() {
private int index = start;
@Override
public boolean hasNext() {
return index < end;
}
@Override
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return index++;
}
};
}
public static void main(String[] args) {
var iterator = range(0, 10);
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// or using a lambda
iterator.forEachRemaining(System.out::println);
}
}
As of Java 5, objects implementing the Template:Javadoc:SE interface, which returns an Iterator
from its only method, can be traversed using Java's foreach loop syntax. The Template:Javadoc:SE interface from the Java collections framework extends Iterable
.
Family
implementing the Iterable
interface:import java.util.Iterator;
import java.util.Set;
class Family<E> implements Iterable<E> {
private final Set<E> elements;
public Family(Set<E> elements) {
this.elements = Set.copyOf(elements);
}
@Override
public Iterator<E> iterator() {
return elements.iterator();
}
}
IterableExample
demonstrates the use of class Family
:public class IterableExample {
public static void main(String[] args) {
var weasleys = Set.of(
"Arthur", "Molly", "Bill", "Charlie",
"Percy", "Fred", "George", "Ron", "Ginny"
);
var family = new Family<>(weasleys);
for (var name : family) {
System.out.println(name + " Weasley");
}
}
}
Ron Weasley
Molly Weasley
Percy Weasley
Fred Weasley
Charlie Weasley
George Weasley
Arthur Weasley
Ginny Weasley
Bill Weasley
Here is another example in Java:
import java.util.BitSet;
import java.util.Iterator;
public class BitSetIterator implements Iterator<Boolean> {
private final BitSet bitset;
private int index = 0;
public BitSetIterator(BitSet bitset) {
this.bitset = bitset;
}
public boolean hasNext() {
return index < bitset.length();
}
public Boolean next() {
if (index >= bitset.length()) {
throw new NoSuchElementException();
}
return bitset.get(index++);
}
public void remove() {
throw new UnsupportedOperationException();
}
}
Two different usage examples:
import java.util.BitSet;
public class TestClientBitSet {
public static void main(String[] args) {
// create BitSet and set some bits
BitSet bitset = new BitSet();
bitset.set(1);
bitset.set(3400);
bitset.set(20);
bitset.set(47);
for (BitSetIterator iter = new BitSetIterator(bitset); iter.hasNext(); ) {
Boolean b = iter.next();
String tf = (b.booleanValue() ? "T" : "F");
System.out.print(tf);
}
System.out.println();
}
}
import java.util.ArrayList;
import java.util.Collection;
public class TestClientIterator {
public static void main(String[] args) {
Collection<Object> al = new ArrayList<Object>();
al.add(new Integer(42));
al.add("test");
al.add(new Double("-12.34"));
for (Iterator<Object> iter = al.iterator(); iter.hasNext(); ) {
System.out.println(iter.next());
}
for (Object o : al) {
System.out.println(o);
}
}
}
JavaScript, as part of ECMAScript 6, supports the iterator pattern with any object that provides a next()
method, which returns an object with two specific properties: done
and value
. Here's an example that shows a reverse array iterator:
function reverseArrayIterator(array) {
var index = array.length - 1;
return {
next: () =>
index >= 0 ?
{value: array[index--], done: false} :
{done: true}
}
}
const it = reverseArrayIterator(['three', 'two', 'one']);
console.log(it.next().value); //-> 'one'
console.log(it.next().value); //-> 'two'
console.log(it.next().value); //-> 'three'
console.log(`Are you done? ${it.next().done}`); //-> true
Most of the time, though, it is desirable to provide Iterator[1] semantics on objects so that they can be iterated automatically via for...of
loops. Some of JavaScript's built-in types such as Array
, Map
, or Set
already define their own iteration behavior. The same effect can be achieved by defining an object's meta @@iterator
method, also referred to by Symbol.iterator
. This creates an Iterable object.
Here's an example of a range function that generates a list of values starting from start
to end
, exclusive, using a regular for
loop to generate the numbers:
function range(start, end) {
return {
[Symbol.iterator]() { // #A
return this;
},
next() {
if (start < end) {
return { value: start++, done: false }; // #B
}
return { done: true, value: end }; // #B
}
}
}
for (number of range(1, 5)) {
console.log(number); // -> 1, 2, 3, 4
}
The iteration mechanism of built-in types, like strings, can also be manipulated:
let iter = ['I', 't', 'e', 'r', 'a', 't', 'o', 'r'][Symbol.iterator]();
iter.next().value; //-> I
iter.next().value; //-> t
.NET Framework has special interfaces that support a simple iteration: System.Collections.IEnumerator
over a non-generic collection and System.Collections.Generic.IEnumerator<T>
over a generic collection.
C# statement foreach
is designed to easily iterate through the collection that implements System.Collections.IEnumerator
and/or System.Collections.Generic.IEnumerator<T>
interface. Since C# v2, foreach
is also able to iterate through types that implement System.Collections.Generic.IEnumerable<T>
and System.Collections.Generic.IEnumerator<T>
[2]
Example of using foreach
statement:
var primes = new List<int>{ 2, 3, 5, 7, 11, 13, 17, 19 };
long m = 1;
foreach (var prime in primes)
m *= prime;
Here is another example in C#:
using System;
using System.Collections;
class MainApp
{
static void Main()
{
ConcreteAggregate a = new ConcreteAggregate();
a[0] = "Item A";
a[1] = "Item B";
a[2] = "Item C";
a[3] = "Item D";
// Create Iterator and provide aggregate
ConcreteIterator i = new ConcreteIterator(a);
Console.WriteLine("Iterating over collection:");
object item = i.First();
while (item != null)
{
Console.WriteLine(item);
item = i.Next();
}
// Wait for user
Console.Read();
}
}
// "Aggregate"
abstract class Aggregate
{
public abstract Iterator CreateIterator();
}
// "ConcreteAggregate"
class ConcreteAggregate : Aggregate
{
private ArrayList items = new ArrayList();
public override Iterator CreateIterator()
{
return new ConcreteIterator(this);
}
// Property
public int Count
{
get{ return items.Count; }
}
// Indexer
public object this[int index]
{
get{ return items[index]; }
set{ items.Insert(index, value); }
}
}
// "Iterator"
abstract class Iterator
{
public abstract object First();
public abstract object Next();
public abstract bool IsDone();
public abstract object CurrentItem();
}
// "ConcreteIterator"
class ConcreteIterator : Iterator
{
private ConcreteAggregate aggregate;
private int current = 0;
// Constructor
public ConcreteIterator(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
}
public override object First()
{
return aggregate[0];
}
public override object Next()
{
object ret = null;
if (current < aggregate.Count - 1)
{
ret = aggregate[++current];
}
return ret;
}
public override object CurrentItem()
{
return aggregate[current];
}
public override bool IsDone()
{
return current >= aggregate.Count ? true : false ;
}
}
PHP supports the iterator pattern via the Iterator interface, as part of the standard distribution.[3] Objects that implement the interface can be iterated over with the foreach
language construct.
Example of patterns using PHP:
<?php
// BookIterator.php
namespace DesignPatterns;
class BookIterator implements \Iterator
{
private int $i_position = 0;
private BookCollection $booksCollection;
public function __construct(BookCollection $booksCollection)
{
$this->booksCollection = $booksCollection;
}
public function current()
{
return $this->booksCollection->getTitle($this->i_position);
}
public function key(): int
{
return $this->i_position;
}
public function next(): void
{
$this->i_position++;
}
public function rewind(): void
{
$this->i_position = 0;
}
public function valid(): bool
{
return !is_null($this->booksCollection->getTitle($this->i_position));
}
}
<?php
// BookCollection.php
namespace DesignPatterns;
class BookCollection implements \IteratorAggregate
{
private array $a_titles = array();
public function getIterator()
{
return new BookIterator($this);
}
public function addTitle(string $string): void
{
$this->a_titles[] = $string;
}
public function getTitle($key)
{
if (isset($this->a_titles[$key])) {
return $this->a_titles[$key];
}
return null;
}
public function is_empty(): bool
{
return empty($this->$a_titles);
}
}
<?php
// index.php
require 'vendor/autoload.php';
use DesignPatterns\BookCollection;
$booksCollection = new BookCollection();
$booksCollection->addTitle('Design Patterns');
$booksCollection->addTitle('PHP7 is the best');
$booksCollection->addTitle('Laravel Rules');
$booksCollection->addTitle('DHH Rules');
foreach ($booksCollection as $book) {
var_dump($book);
}
Output
string(15) "Design Patterns" string(16) "PHP7 is the best" string(13) "Laravel Rules" string(9) "DHH Rules"
Another example: As a default behavior in PHP 5, using an object in a foreach structure will traverse all public values. Multiple Iterator classes are available with PHP to allow you to iterate through common lists, such as directories, XML structures and recursive arrays. It's possible to define your own Iterator classes by implementing the Iterator interface, which will override the default behavior. The Iterator interface definition:
interface Iterator
{
// Returns the current value
function current();
// Returns the current key
function key();
// Moves the internal pointer to the next element
function next();
// Moves the internal pointer to the first element
function rewind();
// If the current element is valid (boolean)
function valid();
}
These methods are all being used in a complete foreach( $object as $key=>$value )
sequence. The methods are executed in the following order:
rewind()
while valid() {
current() in $value
key() in $key
next()
}
End of Loop
According to Zend, the current()
method is called before and after the valid() method.
In Perl, objects providing an iterator interface either overload the <>
(iterator operator),[4] or provide a hash or tied hash interface that can be iterated over with each
.[5] Both <>
and each
return undef
when iteration is complete.
Overloaded <> operator:
# fibonacci sequence
package FibIter;
use overload
'<>' => 'next_fib';
sub new {
my $class = shift;
bless { index => 0, values => [0, 1] }, $class
}
sub next_fib {
my $self = shift;
my $i = $self->{index}++;
$self->{values}[$i] ||=
$i > 1 ? $self->{values}[-2]+$self->{values}[-1]
: ($self->{values}[$i]);
}
# reset iterator index
sub reset {
my $self = shift;
$self->{index} = 0
}
package main;
my $iter = FibIter->new;
while (my $fib = <$iter>) {
print "$fib","\n";
}
Iterating over a hash (or tied hash):
# read from a file like a hash
package HashIter;
use base 'Tie::Hash';
sub new {
my ($class, $fname) = @_;
my $obj = bless {}, $class;
tie %$obj, $class, $fname;
bless $obj, $class;
}
sub TIEHASH {
# tie hash to a file
my $class = shift;
my $fname = shift or die 'Need filename';
die "File $fname must exist"
unless [-f $fname];
open my $fh, '<', $fname or die "open $!";
bless { fname => $fname, fh => $fh }, $class;
}
sub FIRSTKEY {
# (re)start iterator
my $self = shift;
my $fh = $self->{fh};
if (not fileno $self->{fh}) {
open $fh, '<', $self->{fname} or die "open $!";
}
# reset file pointer
seek( $fh, 0, 0 );
chomp(my $line = <$fh>);
$line
}
sub NEXTKEY {
# next item from iterator
my $self = shift;
my $fh = $self->{fh};
return if eof($fh);
chomp(my $line = <$fh>);
$line
}
sub FETCH {
# get value for key, in this case we don't
# care about the values, just return
my ($self, $key) = @_;
return
}
sub main;
# iterator over a word file
my $word_iter = HashIter->new('/usr/share/dict/words');
# iterate until we get to abacus
while (my $word = each( %$word_iter )) {
print "$word\n";
last if $word eq 'abacus'
}
# call keys %tiedhash in void context to reset iterator
keys %$word_iter;
Python prescribes a syntax for iterators as part of the language itself, so that language keywords such as for
work with what Python calls iterables. An iterable has an __iter__()
method that returns an iterator object. The "iterator protocol" requires next()
return the next element or raise a StopIteration
exception upon reaching the end of the sequence. Iterators also provide an __iter__()
method returning themselves so that they can also be iterated over; e.g., using a for
loop. Generators are available since 2.2.
In Python 3, next()
was renamed __next__()
.[6]
In Python, iterators are objects that adhere to the iterator protocol. You can get an iterator from any sequence (i.e. collection: lists, tuples, dictionaries, sets, etc.) with the iter()
method. Another way to get an iterator is to create a generator, which is a kind of iterator. To get the next element from an iterator, you use the next()
method (Python 2) / next()
function (Python 3). When there are no more elements, it raises the StopIteration
exception. To implement your own iterator, you just need an object that implements the next()
method (Python 2) / __next__()
method (Python 3).
Here are two use cases:
# from a sequence
x = [42, "test", -12.34]
it = iter(x)
try:
while True:
x = next(it) # in Python 2, you would use it.next()
print x
except StopIteration:
pass
# a generator
def foo(n):
for i in range(n):
yield i
it = foo(5)
try:
while True:
x = next(it) # in Python 2, you would use it.next()
print x
except StopIteration:
pass
Raku provides APIs for iterators, as part of the language itself, for objects that can be iterated with for
and related iteration constructs, like assignment to a Positional
variable.[7][8] An iterable must at least implement an iterator
method that returns an iterator object. The "iterator protocol" requires the pull-one
method to return the next element if possible, or return the sentinel value IterationEnd
if no more values could be produced. The iteration APIs is provided by composing the Iterable
role, Iterator
, or both, and implementing the required methods.
To check if a type object or an object instance is iterable, the does
method can be used:
say Array.does(Iterable); #=> True
say [1, 2, 3].does(Iterable); #=> True
say Str.does(Iterable); #=> False
say "Hello".does(Iterable); #=> False
The does
method returns True
if and only if the invocant conforms to the argument type.
Here's an example of a range
subroutine that mimics Python's range
function:
multi range(Int:D $start, Int:D $end where * <= $start, Int:D $step where * < 0 = -1) {
(class {
also does Iterable does Iterator;
has Int ($.start, $.end, $.step);
has Int $!count = $!start;
method iterator { self }
method pull-one(--> Mu) {
if $!count > $!end {
my $i = $!count;
$!count += $!step;
return $i;
}
else {
$!count = $!start;
return IterationEnd;
}
}
}).new(:$start, :$end, :$step)
}
multi range(Int:D $start, Int:D $end where * >= $start, Int:D $step where * > 0 = 1) {
(class {
also does Iterable does Iterator;
has Int ($.start, $.end, $.step);
has Int $!count = $!start;
method iterator { self }
method pull-one(--> Mu) {
if $!count < $!end {
my $i = $!count;
$!count += $!step;
return $i;
}
else {
$!count = $!start;
return IterationEnd;
}
}
}).new(:$start, :$end, :$step)
}
my \x = range(1, 5);
.say for x;
# OUTPUT:
# 1
# 2
# 3
# 4
say x.map(* ** 2).sum;
# OUTPUT:
# 30
my \y = range(-1, -5);
.say for y;
# OUTPUT:
# -1
# -2
# -3
# -4
say y.map(* ** 2).sum;
# OUTPUT:
# 30
MATLAB supports both external and internal implicit iteration using either "native" arrays or cell
arrays. In the case of external iteration where the onus is on the user to advance the traversal and request next elements, one can define a set of elements within an array storage structure and traverse the elements using the for
-loop construct. For example,
% Define an array of integers
myArray = [1,3,5,7,11,13];
for n = myArray
% ... do something with n
disp(n) % Echo integer to Command Window
end
traverses an array of integers using the for
keyword.
In the case of internal iteration where the user can supply an operation to the iterator to perform over every element of a collection, many built-in operators and MATLAB functions are overloaded to execute over every element of an array and return a corresponding output array implicitly. Furthermore, the arrayfun
and cellfun
functions can be leveraged for performing custom or user defined operations over "native" arrays and cell
arrays respectively. For example,
function simpleFun
% Define an array of integers
myArray = [1,3,5,7,11,13];
% Perform a custom operation over each element
myNewArray = arrayfun(@(a)myCustomFun(a),myArray);
% Echo resulting array to Command Window
myNewArray
function outScalar = myCustomFun(inScalar)
% Simply multiply by 2
outScalar = 2*inScalar;
defines a primary function simpleFun
which implicitly applies custom subfunction myCustomFun
to each element of an array using built-in function arrayfun
.
Alternatively, it may be desirable to abstract the mechanisms of the array storage container from the user by defining a custom object-oriented MATLAB implementation of the Iterator Pattern. Such an implementation supporting external iteration is demonstrated in MATLAB Central File Exchange item Design Pattern: Iterator (Behavioural). This is written in the new class-definition syntax introduced with MATLAB software version 7.6 (R2008a)
[9]
and features a one-dimensional cell
array realisation of the List Abstract Data Type (ADT) as the mechanism for storing a heterogeneous (in data type) set of elements. It provides the functionality for explicit forward List traversal with the hasNext()
, next()
and reset()
methods for use in a while
-loop.
References
- ↑ "Iterators and generators". Retrieved 18 March 2016.
- ↑ "C# foreach statement".
- ↑ "PHP: Iterator". Retrieved 23 June 2013.
- ↑ File handle objects implement this to provide line by line reading of their contents
- ↑ In Perl 5.12, arrays and tied arrays can be iterated over like hashes, with
each
- ↑ "Python v2.7.1 documentation: The Python Standard Library: 5. Built-in Types". Retrieved 2 May 2011.
- ↑ "Raku documentation: role Iterable". Retrieved 9 December 2020.
- ↑ "Raku documentation: role Iterator". Retrieved 9 December 2020.
- ↑ "New Class-Definition Syntax Introduced with MATLAB Software Version 7.6". The MathWorks, Inc. March 2009. Retrieved September 22, 2009.
Mediator
[edit | edit source]
This pattern defines an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. This pattern helps to model a class whose object at run-time is responsible for controlling and coordinating the interactions of a group of other objects.
Participants
Mediator — defines the interface for communication between Colleague objects. ConcreteMediator — implements the Mediator interface and coordinates communication between Colleague objects. It is aware of all the Colleagues and their purpose with regards to inter communication. ConcreteColleague — communicates with other Colleagues through its Mediator.
Examples
Cost
This pattern is not expensive because there is not much constraint on it.
Creation
This pattern is easy to create.
Maintenance
This pattern is easy to maintain.
Removal
Each object can easily be transformed to another structure using refactoring.
Advises
- Put the mediator term in the name of the iterator class to indicate the use of the pattern to the other developers.
Implementations
// Colleague interface
interface Command {
void execute();
}
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
// Concrete mediator
class Mediator {
BtnView btnView;
BtnSearch btnSearch;
BtnBook btnBook;
LblDisplay show;
//....
void registerView(BtnView v) {
btnView = v;
}
void registerSearch(BtnSearch s) {
btnSearch = s;
}
void registerBook(BtnBook b) {
btnBook = b;
}
void registerDisplay(LblDisplay d) {
show = d;
}
void book() {
btnBook.setEnabled(false);
btnView.setEnabled(true);
btnSearch.setEnabled(true);
show.setText("booking...");
}
void view() {
btnView.setEnabled(false);
btnSearch.setEnabled(true);
btnBook.setEnabled(true);
show.setText("viewing...");
}
void search() {
btnSearch.setEnabled(false);
btnView.setEnabled(true);
btnBook.setEnabled(true);
show.setText("searching...");
}
}
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
// A concrete colleague
class BtnView extends JButton implements Command {
Mediator med;
BtnView(ActionListener al, Mediator m) {
super("View");
addActionListener(al);
med = m;
med.registerView(this);
}
public void execute() {
med.view();
}
}
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
// A concrete colleague
class BtnSearch extends JButton implements Command {
Mediator med;
BtnSearch(ActionListener al, Mediator m) {
super("Search");
addActionListener(al);
med = m;
med.registerSearch(this);
}
public void execute() {
med.search();
}
}
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
// A concrete colleague
class BtnBook extends JButton implements Command {
Mediator med;
BtnBook(ActionListener al, Mediator m) {
super("Book");
addActionListener(al);
med = m;
med.registerBook(this);
}
public void execute() {
med.book();
}
}
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
class LblDisplay extends JLabel {
Mediator med;
LblDisplay(Mediator m) {
super("Just start...");
med = m;
med.registerDisplay(this);
setFont(new Font("Arial", Font.BOLD, 24));
}
}
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
class MediatorDemo extends JFrame implements ActionListener {
Mediator med = new Mediator();
MediatorDemo() {
JPanel p = new JPanel();
p.add(new BtnView(this, med));
p.add(new BtnBook(this, med));
p.add(new BtnSearch(this, med));
getContentPane().add(new LblDisplay(med), "North");
getContentPane().add(p, "South");
setSize(400, 200);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Command comd = (Command) ae.getSource();
comd.execute();
}
public static void main(String[] args) {
new MediatorDemo();
}
}
using System;
using System.Collections;
class MainApp
{
static void Main()
{
ConcreteMediator m = new ConcreteMediator();
ConcreteColleague1 c1 = new ConcreteColleague1(m);
ConcreteColleague2 c2 = new ConcreteColleague2(m);
m.Colleague1 = c1;
m.Colleague2 = c2;
c1.Send("How are you?");
c2.Send("Fine, thanks");
// Wait for user
Console.Read();
}
}
// "Mediator"
abstract class Mediator
{
public abstract void Send(string message,
Colleague colleague);
}
// "ConcreteMediator"
class ConcreteMediator : Mediator
{
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;
public ConcreteColleague1 Colleague1
{
set{ colleague1 = value; }
}
public ConcreteColleague2 Colleague2
{
set{ colleague2 = value; }
}
public override void Send(string message,
Colleague colleague)
{
if (colleague == colleague1)
{
colleague2.Notify(message);
}
else
{
colleague1.Notify(message);
}
}
}
// "Colleague"
abstract class Colleague
{
protected Mediator mediator;
// Constructor
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
}
// "ConcreteColleague1"
class ConcreteColleague1 : Colleague
{
// Constructor
public ConcreteColleague1(Mediator mediator)
: base(mediator)
{
}
public void Send(string message)
{
mediator.Send(message, this);
}
public void Notify(string message)
{
Console.WriteLine("Colleague1 gets message: "
+ message);
}
}
// "ConcreteColleague2"
class ConcreteColleague2 : Colleague
{
// Constructor
public ConcreteColleague2(Mediator mediator)
: base(mediator)
{
}
public void Send(string message)
{
mediator.Send(message, this);
}
public void Notify(string message)
{
Console.WriteLine("Colleague2 gets message: "
+ message);
}
}
Memento
[edit | edit source]
Briefly, the Originator (the object to be saved) creates a snap-shot of itself as a Memento object, and passes that reference to the Caretaker object. The Caretaker object keeps the Memento until such a time as the Originator may want to revert to a previous state as recorded in the Memento object.
The following Java program illustrates the "undo" usage of the Memento Pattern.
class Originator {
private String state;
// The class could also contain additional data that is not part of the
// state saved in the memento.
public void set(String state) {
System.out.println("Originator: Setting state to " + state);
this.state = state;
}
public Memento saveToMemento() {
System.out.println("Originator: Saving to Memento.");
return new Memento(state);
}
public void restoreFromMemento(Memento memento) {
state = memento.getSavedState();
System.out.println("Originator: State after restoring from Memento: " + state);
}
public static class Memento {
private final String state;
private Memento(String stateToSave) {
state = stateToSave;
}
private String getSavedState() {
return state;
}
}
}
import java.util.List;
import java.util.ArrayList;
class Caretaker {
public static void main(String[] args) {
List<Originator.Memento> savedStates = new ArrayList<Originator.Memento>();
Originator originator = new Originator();
originator.set("State1");
originator.set("State2");
savedStates.add(originator.saveToMemento());
originator.set("State3");
// We can request multiple mementos, and choose which one to roll back to.
savedStates.add(originator.saveToMemento());
originator.set("State4");
originator.restoreFromMemento(savedStates.get(1));
}
}
The output is:
Originator: Setting state to State1 Originator: Setting state to State2 Originator: Saving to Memento. Originator: Setting state to State3 Originator: Saving to Memento. Originator: Setting state to State4 Originator: State after restoring from Memento: State3
C# Example
using System;
namespace DoFactory.GangOfFour.Memento.Structural
{
// MainApp startup class for Structural
// Memento Design Pattern.
class MainApp
{
// Entry point into console application.
static void Main()
{
Originator o = new Originator();
o.State = "On";
// Store internal state
Caretaker c = new Caretaker();
c.Memento = o.CreateMemento();
// Continue changing originator
o.State = "Off";
// Restore saved state
o.SetMemento(c.Memento);
// Wait for user
Console.ReadKey();
}
}
// The 'Originator' class
class Originator
{
private string _state;
// Property
public string State
{
get { return _state; }
set
{
_state = value;
Console.WriteLine("State = " + _state);
}
}
// Creates memento
public Memento CreateMemento()
{
return (new Memento(_state));
}
// Restores original state
public void SetMemento(Memento memento)
{
Console.WriteLine("Restoring state...");
State = memento.State;
}
}
// The 'Memento' class
class Memento
{
private readonly string _state;
// Constructor
public Memento(string state) {
this._state = state;
}
// Gets or sets state
public string State
{
get { return _state; }
}
}
// The 'Caretaker' class
class Caretaker
{
private Memento _memento;
// Gets or sets memento
public Memento Memento
{
set { _memento = value; }
get { return _memento; }
}
}
}
Another way to implement memento in C#
public interface IOriginator
{
IMemento GetState();
}
public interface IShape : IOriginator
{
void Draw();
void Scale(double scale);
void Move(double dx, double dy);
}
public interface IMemento
{
void RestoreState();
}
public class CircleOriginator : IShape
{
private class CircleMemento : IMemento
{
private readonly double x;
private readonly double y;
private readonly double r;
private readonly CircleOriginator originator;
public CircleMemento(CircleOriginator originator)
{
this.originator = originator;
x = originator.x;
y = originator.y;
r = originator.r;
}
public void RestoreState()
{
originator.x = x;
originator.y = y;
originator.r = r;
}
}
double x;
double y;
double r;
public CircleOriginator(double x, double y, double r)
{
this.x = x;
this.y = y;
this.r = r;
}
public void Draw()
{
Console.WriteLine("Circle with radius {0} at ({1}, {2})", r, x, y);
}
public void Scale(double scale)
{
r *= scale;
}
public void Move(double dx, double dy)
{
x += dx;
y += dy;
}
public IMemento GetState()
{
return new CircleMemento(this);
}
}
public class RectOriginator : IShape
{
private class RectMemento : IMemento
{
private readonly double x;
private readonly double y;
private readonly double w;
private readonly double h;
private readonly RectOriginator originator;
public RectMemento(RectOriginator originator)
{
this.originator = originator;
x = originator.x;
y = originator.y;
w = originator.w;
h = originator.h;
}
public void RestoreState()
{
originator.x = x;
originator.y = y;
originator.w = w;
originator.h = h;
}
}
double x;
double y;
double w;
double h;
public RectOriginator(double x, double y, double w, double h)
{
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
public void Draw()
{
Console.WriteLine("Rectangle {0}x{1} at ({2}, {3})", w, h, x, y);
}
public void Scale(double scale)
{
w *= scale;
h *= scale;
}
public void Move(double dx, double dy)
{
x += dx;
y += dy;
}
public IMemento GetState()
{
return new RectMemento(this);
}
}
public class Caretaker
{
public void Draw(IEnumerable<IShape> shapes)
{
foreach(IShape shape in shapes)
{
shape.Draw();
}
}
public void MoveAndScale(IEnumerable<IShape> shapes)
{
foreach(IShape shape in shapes)
{
shape.Scale(10);
shape.Move(3, 2);
}
}
public IEnumerable<IMemento> SaveStates(IEnumerable<IShape> shapes)
{
List<IMemento> states = new List<IMemento>();
foreach(IShape shape in shapes)
{
states.Add(shape.GetState());
}
return states;
}
public void RestoreStates(IEnumerable<IMemento> states)
{
foreach(IMemento state in states)
{
state.RestoreState();
}
}
public static void Main()
{
IShape[] shapes = { new RectOriginator(10, 20, 3, 5), new CircleOriginator(5, 2, 10) };
//Outputs:
// Rectangle 3x5 at (10, 20)
// Circle with radius 10 at (5, 2)
Draw(shapes);
//Save states of figures
IEnumerable<IMemento> states = SaveStates(shapes);
//Change placement of figures
MoveAndScale(shapes);
//Outputs:
// Rectangle 30x50 at (13, 22)
// Circle with radius 100 at (8, 4)
Draw(shapes);
//Restore old placement of figures
RestoreStates(states);
//Outputs:
// Rectangle 3x5 at (10, 20)
// Circle with radius 10 at (5, 2)
Draw(shapes);
}
}
{$apptype console}
program Memento;
uses
SysUtils, Classes;
type
TMemento = class
private
_state: string;
function GetSavedState: string;
public
constructor Create(stateToSave: string);
property SavedState: string read GetSavedState;
end;
TOriginator = class
private
_state: string;
// The class could also contain additional data that is not part of the
// state saved in the memento.
procedure SetState(const state: string);
public
function SaveToMemento: TMemento;
procedure RestoreFromMemento(Memento: TMemento);
property state: string read _state write SetState;
end;
TCaretaker = class
private
_memento: TMemento;
public
property Memento: TMemento read _memento write _memento;
end;
{ TMemento }
constructor TMemento.Create(stateToSave: string);
begin
_state := stateToSave;
end;
function TMemento.GetSavedState: string;
begin
writeln('restoring state from Memento');
result := _state;
end;
{ TOriginator }
procedure TOriginator.RestoreFromMemento(Memento: TMemento);
begin
_state := Memento.SavedState;
writeln('Originator: State after restoring from Memento: ' + state);
end;
function TOriginator.SaveToMemento: TMemento;
begin
writeln('Originator: Saving to Memento.');
result := TMemento.Create(state);
end;
procedure TOriginator.SetState(const state: string);
begin
writeln('Originator: Setting state to ' + state);
_state := state;
end;
var
originator: TOriginator;
c1,c2: TCaretaker;
begin
originator := TOriginator.Create;
originator.SetState('State1');
originator.SetState('State2');
// Store internal state
c1 := TCaretaker.Create();
c1.Memento := originator.SaveToMemento();
originator.SetState('State3');
// We can request multiple mementos, and choose which one to roll back to.
c2 := TCaretaker.Create();
c2.Memento := originator.SaveToMemento();
originator.SetState('State4');
// Restore saved state
originator.RestoreFromMemento(c1.Memento);
originator.RestoreFromMemento(c2.Memento);
c1.Memento.Free;
c1.Free;
c2.Memento.Free;
c2.Free;
originator.Free;
end.
import java.util.Date
import common.patterns.Originator.Memento
import scala.collection.immutable.TreeMap
object Originator {
case class Memento(x: Int, y: Int, time: Date)
}
case class Originator(var x: Int, var y: Int) {
def setState(x: Int, y: Int) {
this.x = x
this.y = y
}
def createMemento(): Memento = Memento(x, y, new Date())
def restoreFromMemento(restore: Memento) {
this.x = restore.x
this.y = restore.y
}
}
object Caretaker extends App {
var states: TreeMap[Date, Memento] = new TreeMap
val originator = new Originator(0, 0)
var memento = originator.createMemento()
states += (memento.time -> memento)
Thread.sleep(100)
originator.setState(5, 4)
memento = originator.createMemento()
states += (memento.time -> memento)
Thread.sleep(100)
originator.setState(10, 10)
memento = originator.createMemento()
states += (memento.time -> memento)
originator.restoreFromMemento(states(states.drop(1).firstKey)) //restore second state
println(originator)
}
Output:
Originator(5,4)
Model–view–controller
[edit | edit source]
The model-view-controller (MVC) pattern is an architectural pattern used primarily in creating Graphic User Interfaces (GUIs). The major premise of the pattern is based on modularity and it is to separate three different aspects of the GUI: the data (model), the visual representation of the data (view), and the interface between the view and the model (controller). The primary idea behind keeping these three components separate is so that each one is as independent of the others as possible, and changes made to one will not affect changes made to the others. In this way, for instance, the GUI can be updated with a new look or visual style without having to change the data model or the controller.
Newcomers will probably see this MVC pattern as wasteful, mainly because you are working with many extra objects at runtime, when it seems like one giant object will do. But the secret to the MVC pattern is not writing the code, but in maintaining it, and allowing people to modify the code without changing much else. Different developers have different strengths and weaknesses, so team building around MVC is easier. Imagine a View Team that is responsible for great views, a Model Team that knows a lot about data, and a Controller Team that sees the big picture of application flow, handing requests, working with the model, and selecting the most appropriate next view for that client.
One of the great advantages of the Model-View-Controller Pattern is the ability to reuse the application's logic (which is implemented in the model) when implementing a different view. A good example is found in web development, where a common task is to implement an external API inside of an existing piece of software. If the MVC pattern has cleanly been followed, this only requires modification to the controller, which can have the ability to render different types of views dependent on the content type requested by the user agent.
Model
Generally, the model is constructed first. The model has two jobs: it must both store a state and manage subscribers. The state does not need to be anything special; you simply need to define how you're going to store data, with setters and getters. However, anything which can change (any property) must have a list of listeners which it contacts whenever the value changes. The property listeners allow us to have multiple views on the same data, which are all live-updated when the state changes. The code for this can usually be defined in a superclass and inherited, so that you just write it in one place and then it applies consistently to every property. Nested states (for example, dynamically configured properties) may require some extra thinking about how you want to report the changes.
People sometimes use the word 'model' to refer to the 'data model' -- the architecture of the data structures in the application. A good MVC framework takes care of the model superclass and subscriptions for you, so that you can simply define your own data structure in that framework's model-language, and then immediately build the other components. In this end-user sense, defining the data model is equivalent to defining a model. However, if you are designing a framework, it is not MVC if it lacks property listeners.
View
Once you write a data model, the next easiest thing to write is usually a view. The view is the part of the application which subscribes to a model. Usually it presents it to a user alongside a user interface, or GUI. The GUI contains other components too, which are usually part of the controller and can be handled later.
You can also have view-controller components which have nothing to do with user interfaces. You can imagine, for example, an MVC circuit-board application where a model simply manages numbers (voltages and currents) throughout the circuit. A resistor, for example, then has a "view" of the voltages at each end, tightly coupled to a "controller" which updates the current going through that resistor. All of the components talking to each other through the model would then eventually perform the circuit's actions in real-time.
When you're writing a view, there are two things to think about: "what do I do when the state changes?" and "how do I display this to the user?" Your MVC framework usually provides editors for various properties in the model, like date selectors, text fields, sliding bars, and combo boxes. More complex properties often require more complex views and editors, like tree views. Your MVC framework will probably have already figured out how to connect these components to the model, and might even auto-generate appropriate components based on the type of a given property in the model.
Controller
The rest of the GUI -- the parts which do not update when the model changes -- are the responsibility of the controller. This includes navigating around the view, as well as what you do when someone tries to edit the data in the view. Strictly speaking, a view cannot be edited and is 'read-only' -- when you try to modify a field in the view, the controller needs to pick up the editing event, process it, and send it to the model; the model will then update the view if/when the value actually changes.
Different frameworks handle controllers in different ways. Some frameworks allow callback functions to be associated with editors, which get called when the value is changed. Other frameworks allow you to add listeners directly to the component, which can be notified when the value in the editor changes, when it is clicked on, or when it loses focus, etc. In many frameworks, the controller appears as a collection of methods and listeners built into both the data model and the view. For example, if you have a "password" property in the model which needs to be salted and hashed before being stored, this logic might appear in a setPassword
function living in the data model. Similarly, when a framework generates a view, the widgets for the view are often not read-only but rather read-write, with listeners. The actual controllers provided by the MVC framework then "plug into" each of these interfaces, and pass data between them.
Validation
When possible, it is usually best to allow the model to do all the necessary validation of values, so that any changes to the allowed values, or changes simply to the validation process, only need to be made in one place. However, in some languages under certain circumstances, this may not be possible. For instance, if a numeric property is being edited with a text field, then the value of the property passed to the controller by the view will be text, not a number. In this case, the model could be made to have an additional method that takes text as the input value for this property, but more likely, the controller will do the initial parsing of the text to get the numeric value, and then pass it on to the model to do further validation (for instance, bounds checking). When either the controller or the model determines that a passed in value is invalid, the controller will need to tell the view that the value is invalid. In some cases, the view may then issue an error dialog or other notification, or it may simply revert the value in its editor to the older valid value.
In Java, we can implement a fat client GUI. In this case, we can use:
- JavaBeans to implement the model and,
- SWT or Java Swings to implement the view and the controller.
However, in Java EE, we can also implement a web application. In this case, we can use:
- EJB entity to implement the model,
- JSP to implement the view and,
- EJB session to implement the controller.
Observer
[edit | edit source]
Scope
Object
Purpose
Behavioral
Intent
Define a one-to-many dependency between objects so that when one object changes state (the Subject), all its dependents (the Observers) are notified and updated automatically.
Applicability
- when an abstraction has two aspects, one dependent on the other
- when a change to one object requires changing others, and you don't know how many objects need to be changed
- when an object should notify other objects without making assumptions about who these objects are
Structure
Consequences
- + modularity: subject and observers may vary independently
- + extensibility: can define and add any number of observers
- + customizability: different observers provide different views of subject
- - unexpected updates: observers don't know about each other
- - update overhead: might need hints
Implementation
- subject-observer mapping
- dangling references
- avoiding observer-specific update protocols: the push and pull models
- registering modifications of interest explicitly
Related pattern
- Singleton, is used to make observable object unique and accessible globally.
- Mediator, is used to encapsulate updated objects
Description
- Problem
- In one place or many places in the application we need to be aware about a system event or an application state change. We'd like to have a standard way of subscribing to listening for system events and a standard way of notifying the interested parties. The notification should be automated after an interested party subscribed to the system event or application state change. There should be a way to unsubscribe, too.
- Forces
- Observers and observables probably should be represented by objects. The observer objects will be notified by the observable objects.
- Solution
- After subscribing the listening objects will be notified by a way of method call.
- Loose coupling
- When two objects are loosely coupled, they can interact, but they have very little knowledge of each other. Strive for loosely coupled designs between objects that interact.
- The only thing that Subject knows about an observer is that it implements a certain interface
- We can add new observers at any time
- We never need to modify the subject to add new types of observers
- We can reuse subjects or observers independently of each other
- Changes to either the subject or an observer will not affect the other
Examples
The Observer pattern is used extensively in Java. E.g. in the following piece of code
button
is the SubjectMyListener
is the ObserveractionPerformed()
is the equivalent toupdate()
JButton button = new JButton("Click me!");
button.addActionListener(new MyListener());
class MyListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
...
}
}
Another example is the PropertyChangeSupport
. The Component
class uses a PropertyChangeSupport
object to let interested observers register for notification of changes in the properties of labels, panels, and other GUI components.
Can you find the Subject
, Observer
and update()
in the above class diagram?
Component
is the SubjectPropertyChangeListener
is the ObserverpropertyChange()
is the equivalent toupdate()
Cost
This pattern can be tricky if you do not beware. Beware the data representing the state changes of the subject can evolve without changing the interfaces. If you only transmit a string, the pattern could become very expensive if at least one new observer needs also a state code. You should use a mediator unless you know the implementation of the subject state will never change.
Creation
This pattern has a cost to create.
Maintenance
This pattern can be expensive to maintain.
Removal
This pattern has a cost to remove too.
Advises
- Put the subject and observer term in the name of the subject and the observer classes to indicate the use of the pattern to the other developers.
- To improve performances, you can only send to the observers the difference of states instead of the new state. The observers can only update following the changed part of the subject instead of all the state of the subject.
Implementations
// Main Class
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
private var _cs:ConcreteSubject = new ConcreteSubject();
private var _co1:ConcreteObserver1 = new ConcreteObserver1();
private var _co2:ConcreteObserver2 = new ConcreteObserver2();
public function Main() {
_cs.registerObserver(_co1);
_cs.registerObserver(_co2);
_cs.changeState(10);
_cs.changeState(99);
_cs.unRegisterObserver(_co1);
_cs.changeState(17);
_co1 = null;
}
}
}
// Interface Subject
package {
public interface ISubject {
function registerObserver(o:IObserver):void;
function unRegisterObserver(o:IObserver):void;
function updateObservers():void;
function changeState(newState:uint):void;
}
}
// Interface Observer
package {
public interface IObserver {
function update(newState:uint):void;
}
}
// Concrete Subject
package {
public class ConcreteSubject implements ISubject {
private var _observersList:Array = new Array();
private var _currentState:uint;
public function ConcreteSubject() {
}
public function registerObserver(o:IObserver):void {
_observersList.push( o );
_observersList[_observersList.length-1].update(_currentState); // update newly registered
}
public function unRegisterObserver(o:IObserver):void {
_observersList.splice( _observersList.indexOf( o ), 1 );
}
public function updateObservers():void {
for( var i:uint = 0; i<_observersList.length; i++) {
_observersList[i].update(_currentState);
}
}
public function changeState(newState:uint):void {
_currentState = newState;
updateObservers();
}
}
}
// Concrete Observer 1
package {
public class ConcreteObserver1 implements IObserver {
public function ConcreteObserver1() {
}
public function update(newState:uint):void {
trace( "co1: "+newState );
}
// other Observer specific methods
}
}
// Concrete Observer 2
package {
public class ConcreteObserver2 implements IObserver {
public function ConcreteObserver2() {
}
public function update(newState:uint):void {
trace( "co2: "+newState );
}
// other Observer specific methods
}
}
Traditional Method
C# and the other .NET Framework languages do not typically require a full implementation of the Observer pattern using interfaces and concrete objects. Here is an example of using them, however.
using System;
using System.Collections;
namespace Wikipedia.Patterns.Observer
{
// IObserver --> interface for the observer
public interface IObserver
{
// called by the subject to update the observer of any change
// The method parameters can be modified to fit certain criteria
void Update(string message);
}
public class Subject
{
// use array list implementation for collection of observers
private ArrayList observers;
// constructor
public Subject()
{
observers = new ArrayList();
}
public void Register(IObserver observer)
{
// if list does not contain observer, add
if (!observers.Contains(observer))
{
observers.Add(observer);
}
}
public void Unregister(IObserver observer)
{
// if observer is in the list, remove
observers.Remove(observer);
}
public void Notify(string message)
{
// call update method for every observer
foreach (IObserver observer in observers)
{
observer.Update(message);
}
}
}
// Observer1 --> Implements the IObserver
public class Observer1 : IObserver
{
public void Update(string message)
{
Console.WriteLine("Observer1:" + message);
}
}
// Observer2 --> Implements the IObserver
public class Observer2 : IObserver
{
public void Update(string message)
{
Console.WriteLine("Observer2:" + message);
}
}
// Test class
public class ObserverTester
{
[STAThread]
public static void Main()
{
Subject mySubject = new Subject();
IObserver myObserver1 = new Observer1();
IObserver myObserver2 = new Observer2();
// register observers
mySubject.Register(myObserver1);
mySubject.Register(myObserver2);
mySubject.Notify("message 1");
mySubject.Notify("message 2");
}
}
}
Using Events
The alternative to using concrete and abstract observers and publishers in C# and other .NET Framework languages, such as Visual Basic, is to use events. The event model is supported via delegates that define the method signature that should be used to capture events. Consequently, delegates provide the mediation otherwise provided by the abstract observer, the methods themselves provide the concrete observer, the concrete subject is the class defining the event, and the subject is the event system built into the base class library. It is the preferred method of accomplishing the Observer pattern in.NET applications.
using System;
// First, declare a delegate type that will be used to fire events.
// This is the same delegate as System.EventHandler.
// This delegate serves as the abstract observer.
// It does not provide the implementation, but merely the contract.
public delegate void EventHandler(object sender, EventArgs e);
// Next, declare a published event. This serves as the concrete subject.
// Note that the abstract subject is handled implicitly by the runtime.
public class Button
{
// The EventHandler contract is part of the event declaration.
public event EventHandler Clicked;
// By convention,.NET events are fired from descendant classes by a virtual method,
// allowing descendant classes to handle the event invocation without subscribing
// to the event itself.
protected virtual void OnClicked(EventArgs e)
{
if (Clicked != null)
Clicked(this, e); // implicitly calls all observers/subscribers
}
}
// Then in an observing class, you are able to attach and detach from the events:
public class Window
{
private Button okButton;
public Window()
{
okButton = new Button();
// This is an attach function. Detaching is accomplished with -=.
// Note that it is invalid to use the assignment operator - events are multicast
// and can have multiple observers.
okButton.Clicked += new EventHandler(okButton_Clicked);
}
private void okButton_Clicked(object sender, EventArgs e)
{
// This method is called when Clicked(this, e) is called within the Button class
// unless it has been detached.
}
}
Handy implementation
You can implement this pattern in Java like this:
// Observer pattern -- Structural example
// @since JDK 5.0
import java.util.ArrayList;
// "Subject"
abstract class Subject {
// Fields
private ArrayList<Observer> observers = new ArrayList<Observer>();
// Methods
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void notifyObservers() {
for (Observer o : observers)
o.update();
}
}
// "ConcreteSubject"
class ConcreteSubject extends Subject {
// Fields
private String subjectState;
// Properties
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String value) {
subjectState = value;
}
}
// "Observer"
abstract class Observer {
// Methods
abstract public void update();
}
// "ConcreteObserver"
class ConcreteObserver extends Observer {
// Fields
private String name;
private String observerState;
private ConcreteSubject subject;
// Constructors
public ConcreteObserver(ConcreteSubject subject, String name) {
this.subject = subject;
this.name = name;
//subject.attach(this);
}
// Methods
public void update() {
observerState = subject.getSubjectState();
System.out.printf("Observer %s's new state is %s\n", name, observerState);
}
}
// Client test
public class Client {
public static void main(String[] args) {
// Configure Observer structure
ConcreteSubject s = new ConcreteSubject();
s.attach(new ConcreteObserver(s, "A"));
s.attach(new ConcreteObserver(s, "B"));
s.attach(new ConcreteObserver(s, "C"));
// Change subject and notify observers
s.setSubjectState("NEW");
s.notifyObservers();
}
}
Built-in support
The Java JDK has several implementations of this pattern: application in Graphical User Interfaces such as in the AWT toolkit, Swing etc. In Swing, whenever a user clicks a button or adjusts a slider, many objects in the application may need to react to the change. Swing refers to interested clients (observers) as "listeners" and lets you register as many listeners as you like to be notified of a component's events.
MVC is more M(VC) in Swing, i.e. View and Controller are tightly coupled; Swing does not divide Views from Controllers. MVC supports n-tier development, i.e. loosely coupled layers (see below) that can change independently and that may even execute on different machines.
There is also a built-in support for the Observer pattern. All one has to do is extend java.util.Observable (the Subject) and tell it when to notify the java.util.Observer s. The API does the rest for you. You may use either push or pull style of updating your observers.
java.util.Observable
is a class while java.util.Observer
is an interface.
public void setValue(double value) {
this.value = value;
setChanged();
notifyObservers();
}
Note that you have to call setChanged()
so that the Observable
code will broadcast the change.
The notifyObservers()
method calls the update()
method of each registered observer. The update()
method is a requirement for implementers of the Observer
Interface.
// Observer pattern -- Structural example
import java.util.Observable;
import java.util.Observer;
// "Subject"
class ConcreteSubject extends Observable {
// Fields
private String subjectState;
// Methods
public void dataChanged() {
setChanged();
notifyObservers(); // use the pull method
}
// Properties
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String value) {
subjectState = value;
dataChanged();
}
}
// "ConcreteObserver"
import java.util.Observable;
import java.util.Observer;
class ConcreteObserver implements Observer {
// Fields
private String name;
private String observerState;
private Observable subject;
// Constructors
public ConcreteObserver(Observable subject, String name) {
this.subject = subject;
this.name = name;
subject.addObserver(this);
}
// Methods
public void update(Observable subject, Object arg) {
if (subject instanceof ConcreteSubject) {
ConcreteSubject subj = (ConcreteSubject)subject;
observerState = subj.getSubjectState();
System.out.printf("Observer %s's new state is %s\n", name, observerState);
}
}
}
// Client test
public class Client {
public static void main(String[] args) {
// Configure Observer structure
ConcreteSubject s = new ConcreteSubject();
new ConcreteObserver(s, "A");
new ConcreteObserver(s, "B");
new ConcreteObserver(s, "C");
// Change subject and notify observers
s.setSubjectState("NEW");
}
}
Keyboard handling
Below is an example written in Java that takes keyboard input and treats each input line as an event. The example is built upon the library classes java.util.Observer
and java.util.Observable
. When a string is supplied from System.in, the method notifyObservers
is then called, in order to notify all observers of the event's occurrence, in the form of an invocation of their 'update' methods - in our example, ResponseHandler.update(...)
.
The file MyApp.java
contains a main()
method that might be used in order to run the code.
/* Filename : EventSource.java */
package org.wikibooks.obs;
import java.util.Observable; // Observable is here
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class EventSource extends Observable implements Runnable {
@Override
public void run() {
try {
final InputStreamReader isr = new InputStreamReader(System.in);
final BufferedReader br = new BufferedReader(isr);
while (true) {
String response = br.readLine();
setChanged();
notifyObservers(response);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/* Filename : ResponseHandler.java */
package org.wikibooks.obs;
import java.util.Observable;
import java.util.Observer; /* this is Event Handler */
public class ResponseHandler implements Observer {
private String resp;
public void update(Observable obj, Object arg) {
if (arg instanceof String) {
resp = (String) arg;
System.out.println("\nReceived Response: " + resp );
}
}
}
/* Filename : MyApp.java */
/* This is the main program */
package org.wikibooks.obs;
public class MyApp {
public static void main(String[] args) {
System.out.println("Enter Text >");
// create an event source - reads from stdin
final EventSource eventSource = new EventSource();
// create an observer
final ResponseHandler responseHandler = new ResponseHandler();
// subscribe the observer to the event source
eventSource.addObserver(responseHandler);
// starts the event thread
Thread thread = new Thread(eventSource);
thread.start();
}
}
The Java implementation of the Observer pattern has pros and cons:
Pros
- It hides many of the details of the Observer pattern
- It can be used both pull and push ways.
Cons
- Because
Observable
is a class, you have to subclass it; you can’t add on theObservable
behavior to an existing class that subclasses another superclass (fails the programming to interfaces principle). If you can’t subclassObservable
, then use delegation, i.e. provide your class with an Observable object and have your class forward key method calls to it. - Because
setChanged()
is protected, you can’t favour composition over inheritance.
class STUDENT
<?php
class Student implements SplObserver {
protected $type = "Student";
private $name;
private $address;
private $telephone;
private $email;
private $_classes = array();
public function __construct($name)
{
$this->name = $name;
}
public function GET_type()
{
return $this->type;
}
public function GET_name()
{
return $this->name;
}
public function GET_email()
{
return $this->email;
}
public function GET_telephone()
{
return $this->telephone;
}
public function update(SplSubject $object)
{
$object->SET_log("Comes from ".$this->name.": I'm a student of ".$object->GET_materia());
}
}
?>
class TEACHER
<?php
class Teacher implements SplObserver {
protected $type = "Teacher";
private $name;
private $address;
private $telephone;
private $email;
private $_classes = array();
public function __construct($name)
{
$this->name = $name;
}
public function GET_type()
{
return $this->type;
}
public function GET_name()
{
return $this->name;
}
public function GET_email()
{
return $this->email;
}
public function GET_telephone()
{
return $this->name;
}
public function update(SplSubject $object)
{
$object->SET_log("Comes from ".$this->name.": I teach in ".$object->GET_materia());
}
}
?>
Class SUBJECT
<?php
class Subject implements SplSubject {
private $name_materia;
private $_observers = array();
private $_log = array();
function __construct($name)
{
$this->name_materia = $name;
$this->_log[] = "Subject $name was included";
}
/* Add an observer */
public function attach(SplObserver $classes) {
$this->_classes[] = $classes;
$this->_log[] = " The ".$classes->GET_type()." ".$classes->GET_name()." was included";
}
/* Remove an observer */
public function detach(SplObserver $classes) {
foreach ($this->_classes as $key => $obj) {
if ($obj == $classes) {
unset($this->_classes[$key]);
$this->_log[] = " The ".$classes->GET_type()." ".$classes->GET_name()." was removed";
}
}
}
/* Notificate an observer */
public function notify(){
foreach ($this->_classes as $classes){
$classes->update($this);
}
}
public function GET_materia()
{
return $this->name_materia;
}
function SET_log($valor)
{
$this->_log[] = $valor ;
}
function GET_log()
{
return $this->_log;
}
}
?>
Application
<?php
require_once("teacher.class.php");
require_once("student.class.php");
require_once("subject.class.php");
$subject = new Subject("Math");
$marcus = new Teacher("Marcus Brasizza");
$rafael = new Student("Rafael");
$vinicius = new Student("Vinicius");
// Include observers in the math Subject
$subject->attach($rafael);
$subject->attach($vinicius);
$subject->attach($marcus);
$subject2 = new Subject("English");
$renato = new Teacher("Renato");
$fabio = new Student("Fabio");
$tiago = new Student("Tiago");
// Include observers in the english Subject
$subject2->attach($renato);
$subject2->attach($vinicius);
$subject2->attach($fabio);
$subject2->attach($tiago);
// Remove the instance "Rafael from subject"
$subject->detach($rafael);
// Notify both subjects
$subject->notify();
$subject2->notify();
echo "First Subject <br>";
echo "<pre>";
print_r($subject->GET_log());
echo "</pre>";
echo "<hr>";
echo "Second Subject <br>";
echo "<pre>";
print_r($subject2->GET_log());
echo "</pre>";
?>
OUTPUT
First Subject
Array
(
[0] => Subject Math was included
[1] => The Student Rafael was included
[2] => The Student Vinicius was included
[3] => The Teacher Marcus Brasizza was included
[4] => The Student Rafael was removed
[5] => Comes from Vinicius: I'm a student of Math
[6] => Comes from Marcus Brasizza: I teach in Math
)
Second Subject
Array
(
[0] => Subject English was included
[1] => The Teacher Renato was included
[2] => The Student Vinicius was included
[3] => The Student Fabio was included
[4] => The Student Tiago was included
[5] => Comes from Renato: I teach in English
[6] => Comes from Vinicius: I'm a student of English
[7] => Comes from Fabio: I'm a student of English
[8] => Comes from Tiago: I'm a student of English
)
The observer pattern in Python:
class AbstractSubject:
def register(self, listener):
raise NotImplementedError("Must subclass me")
def unregister(self, listener):
raise NotImplementedError("Must subclass me")
def notify_listeners(self, event):
raise NotImplementedError("Must subclass me")
class Listener:
def __init__(self, name, subject):
self.name = name
subject.register(self)
def notify(self, event):
print self.name, "received event", event
class Subject(AbstractSubject):
def __init__(self):
self.listeners = []
self.data = None
def getUserAction(self):
self.data = raw_input('Enter something to do:')
return self.data
# Implement abstract Class AbstractSubject
def register(self, listener):
self.listeners.append(listener)
def unregister(self, listener):
self.listeners.remove(listener)
def notify_listeners(self, event):
for listener in self.listeners:
listener.notify(event)
if __name__=="__main__":
# make a subject object to spy on
subject = Subject()
# register two listeners to monitor it.
listenerA = Listener("<listener A>", subject)
listenerB = Listener("<listener B>", subject)
# simulated event
subject.notify_listeners ("<event 1>")
# outputs:
# <listener A> received event <event 1>
# <listener B> received event <event 1>
action = subject.getUserAction()
subject.notify_listeners(action)
#Enter something to do:hello
# outputs:
# <listener A> received event hello
# <listener B> received event hello
The observer pattern can be implemented more succinctly in Python using function decorators.
In Ruby, use the standard Observable mixin. For documentation and an example, see http://www.ruby-doc.org/stdlib/libdoc/observer/rdoc/index.html
Prototype
[edit | edit source]
The prototype pattern is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. This pattern is used to:
- avoid subclasses of an object creator in the client application, like the abstract factory pattern does.
- avoid the inherent cost of creating a new object in the standard way (e.g., using the 'new' keyword) when it is prohibitively expensive for a given application.
To implement the pattern, declare an abstract base class that specifies a pure virtual clone() method. Any class that needs a "polymorphic constructor" capability derives itself from the abstract base class, and implements the clone() operation.
The client, instead of writing code that invokes the "new" operator on a hard-coded class name, calls the clone() method on the prototype, calls a factory method with a parameter designating the particular concrete derived class desired, or invokes the clone() method through some mechanism provided by another design pattern.
Structure
Rules of thumb
Sometimes creational patterns overlap — there are cases when either Prototype or Abstract Factory would be appropriate. At other times they complement each other: Abstract Factory might store a set of Prototypes from which to clone and return product objects (GoF, p126). Abstract Factory, Builder, and Prototype can use Singleton in their implementations. (GoF, p81, 134). Abstract Factory classes are often implemented with Factory Methods (creation through inheritance), but they can be implemented using Prototype (creation through delegation). (GoF, p95)
Often, designs 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. (GoF, p136)
Prototype doesn't require subclassing, but it does require an "initialize" operation. Factory Method requires subclassing, but doesn't require initialization. (GoF, p116)
Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well. (GoF, p126)
The rule of thumb could be that you would need to clone() an Object when you want to create another Object at runtime that is a true copy of the Object you are cloning. True copy means all the attributes of the newly created Object should be the same as the Object you are cloning. If you could have instantiated the class by using new instead, you would get an Object with all attributes as their initial values. For example, if you are designing a system for performing bank account transactions, then you would want to make a copy of the Object that holds your account information, perform transactions on it, and then replace the original Object with the modified one. In such cases, you would want to use clone() instead of new.
Advices
- Put the prototype term in the name of the prototype classes to indicate the use of the pattern to the other developers.
- Only use an interface when it is necessary.
Implementations
It specifies the kind of objects to create using a prototypical instance. Prototypes of new products are often built prior to full production, but in this example, the prototype is passive and does not participate in copying itself. The mitotic division of a cell — resulting in two identical cells — is an example of a prototype that plays an active role in copying itself and thus, demonstrates the Prototype pattern. When a cell splits, two cells of identical genotype result. In other words, the cell clones itself.
The concrete type of object is created from its prototype. MemberwiseClone is used in the Clone method to create and return a copy of ConcreteFoo1 or ConcreteFoo2.
public abstract class Foo
{
// normal implementation
public abstract Foo Clone();
}
public class ConcreteFoo1 : Foo
{
public override Foo Clone()
{
return (Foo)this.MemberwiseClone(); // Clones the concrete class.
}
}
public class ConcreteFoo2 : Foo
{
public override Foo Clone()
{
return (Foo)this.MemberwiseClone(); // Clones the concrete class.
}
}
Another example:
//Note: In this example ICloneable interface (defined in .Net Framework) acts as Prototype
class ConcretePrototype : ICloneable
{
public int X { get; set; }
public ConcretePrototype(int x)
{
this.X = x;
}
public void PrintX()
{
Console.WriteLine("Value :" + X);
}
public object Clone()
{
return this.MemberwiseClone();
}
}
/**
* Client code
*/
public class PrototypeTest
{
public static void Main()
{
var prototype = new ConcretePrototype(1000);
for (int i = 1; i < 10; i++)
{
ConcretePrototype tempotype = prototype.Clone() as ConcretePrototype;
// Usage of values in prototype to derive a new value.
tempotype.X *= i;
tempotype.PrintX();
}
Console.ReadKey();
}
}
/*
**Code output**
Value :1000
Value :2000
Value :3000
Value :4000
Value :5000
Value :6000
Value :7000
Value :8000
Value :9000
*/
#include <iostream>
using namespace std;
// Prototype
class Prototype
{
public:
virtual ~Prototype() { }
virtual Prototype* clone() const = 0;
virtual void setX(int x) = 0;
virtual int getX() const = 0;
virtual void printX() const = 0;
};
// Concrete prototype
class ConcretePrototype : public Prototype
{
public:
ConcretePrototype(int x) : x_(x) { }
ConcretePrototype(const ConcretePrototype& p) : x_(p.x_) { }
virtual ConcretePrototype* clone() const { return new ConcretePrototype(*this); }
void setX(int x) { x_ = x; }
int getX() const { return x_; }
void printX() const { std::cout << "Value :" << x_ << std::endl; }
private:
int x_;
};
// Client code
int main()
{
Prototype* prototype = new ConcretePrototype(1000);
for (int i = 1; i < 10; i++) {
Prototype* temporaryPrototype = prototype->clone();
temporaryPrototype->setX(temporaryPrototype->getX() * i);
temporaryPrototype->printX();
delete temporaryPrototype;
}
delete prototype;
return 0;
}
Code output:
Value :1000 Value :2000 Value :3000 Value :4000 Value :5000 Value :6000 Value :7000 Value :8000 Value :9000
This pattern creates the kind of object using its prototype. In other words, while creating the object of Prototype object, the class creates a clone of it and returns it as prototype. The clone method has been used to clone the prototype when required.
// Prototype pattern
public abstract class Prototype implements Cloneable {
public Prototype clone() throws CloneNotSupportedException{
return (Prototype) super.clone();
}
}
public class ConcretePrototype1 extends Prototype {
@Override
public Prototype clone() throws CloneNotSupportedException {
return (ConcretePrototype1)super.clone();
}
}
public class ConcretePrototype2 extends Prototype {
@Override
public Prototype clone() throws CloneNotSupportedException {
return (ConcretePrototype2)super.clone();
}
}
Another example:
/**
* Prototype class
*/
interface Prototype extends Cloneable {
void setX(int x);
void printX();
int getX();
}
/**
* Implementation of prototype class
*/
class PrototypeImpl implements Prototype {
private int x;
/**
* Constructor
*/
public PrototypeImpl(int x) {
setX(x);
}
@Override
public void setX(int x) {
this.x = x;
}
@Override
public void printX() {
System.out.println("Value: " + getX());
}
@Override
public int getX() {
return x;
}
@Override
public PrototypeImpl clone() throws CloneNotSupportedException {
return (PrototypeImpl) super.clone();
}
}
/**
* Client code
*/
public class PrototypeTest {
public static void main(String args[]) throws CloneNotSupportedException {
PrototypeImpl prototype = new PrototypeImpl(1000);
for (int y = 1; y < 10; y++) {
// Create a defensive copy of the object to allow safe mutation
Prototype tempotype = prototype.clone();
// Derive a new value from the prototype's "x" value
tempotype.setX(tempotype.getX() * y);
tempotype.printX();
}
}
}
Code output:
Value: 1000 Value: 2000 Value: 3000 Value: 4000 Value: 5000 Value: 6000 Value: 7000 Value: 8000 Value: 9000
// The Prototype pattern in PHP is done with the use of built-in PHP function __clone()
abstract class Prototype
{
public string $a;
public string $b;
public function displayCONS(): void
{
echo "CONS: {$this->a}\n";
echo "CONS: {$this->b}\n";
}
public function displayCLON(): void
{
echo "CLON: {$this->a}\n";
echo "CLON: {$this->b}\n";
}
abstract function __clone();
}
class ConcretePrototype1 extends Prototype
{
public function __construct()
{
$this->a = "A1";
$this->b = "B1";
$this->displayCONS();
}
function __clone()
{
$this->displayCLON();
}
}
class ConcretePrototype2 extends Prototype
{
public function __construct()
{
$this->a = "A2";
$this->b = "B2";
$this->displayCONS();
}
function __clone()
{
$this->a = $this->a ."-C";
$this->b = $this->b ."-C";
$this->displayCLON();
}
}
$cP1 = new ConcretePrototype1();
$cP2 = new ConcretePrototype2();
$cP2C = clone $cP2;
// RESULT: #quanton81
// CONS: A1
// CONS: B1
// CONS: A2
// CONS: B2
// CLON: A2-C
// CLON: B2-C
Another example:
<?php
class ConcretePrototype {
protected $x;
public function __construct($x) {
$this->x = (int) $x;
}
public function printX() {
echo sprintf('Value: %5d' . PHP_EOL, $this->x);
}
public function setX($x) {
$this->x *= (int) $x;
}
public function __clone() {
/*
* This method is not required for cloning, although when implemented,
* PHP will trigger it after the process in order to permit you some
* change in the cloned object.
*
* Reference: http://php.net/manual/en/language.oop5.cloning.php
*/
// $this->x = 1;
}
}
/**
* Client code
*/
$prototype = new ConcretePrototype(1000);
foreach (range(1, 10) as $i) {
$tempotype = clone $prototype;
$tempotype->setX($i);
$tempotype->printX();
}
/*
**Code output**
Value: 1000
Value: 2000
Value: 3000
Value: 4000
Value: 5000
Value: 6000
Value: 7000
Value: 8000
Value: 9000
Value: 10000
*/
Let's write an occurrence browser class for a text. This class lists the occurrences of a word in a text. Such an object is expensive to create as the locations of the occurrences need an expensive process to find. So, to duplicate such an object, we use the prototype pattern:
class WordOccurrences is field occurrences is The list of the index of each occurrence of the word in the text. constructor WordOccurrences(text, word) is input: the text in which the occurrences have to be found input: the word that should appear in the text Empty the occurrences list for each Template:Not a typo in text Template:Not a typog:= true for each Template:Not a typo in word if the current word character does not match the current text character then Template:Not a typog:= false if Template:Not a typo is true then Add the current Template:Not a typo into the occurrences list method getOneOccurrenceIndex(n) is input: a number to point on the nth occurrence. output: the index of the nth occurrence. Return the nth item of the occurrences field if any. method clone() is output: a WordOccurrences object containing the same data. Call clone() on the super class. On the returned object, set the occurrences field with the value of the local occurrences field. Return the cloned object. texte:= "The prototype pattern is a creational design pattern in software development first described in design patterns, the book." wordw:= "pattern"d searchEnginen:= new WordOccurrences(text, word) anotherSearchEngineE:= searchEngine.clone()
(the search algorithm is not optimized; it is a basic algorithm to illustrate the pattern implementation)
This implementation uses the decorator pattern.
# Decorator class which allows an object to create an exact duplicate of itself
class Prototype:
def _clone_func(self):
# This function will be assigned to the decorated object and can
# be used to create an exact duplicate of that decorated object
clone = self.cls()
# Call _copy_func to ensure the attributes of the objects are identical
self._copy_func(self.instance, clone)
return clone
def _copy_func(self, fromObj, toObj):
# Dual purpose function which is assigned to the decorated object
# and used internally in the decorator to copy the original attributes
# to the clone to ensure it's identical to the object which made the clone
for attr in dir(fromObj):
setattr(toObj, attr, getattr(fromObj, attr))
def __init__(self, cls):
# This is only called once per decorated class type so self.cls
# should remember the class that called it so it can generate
# unique objects of that class later on (in __call__)
self.cls = cls
# NOTE: on a decorator "__call__" MUST be implemented
# this function will automatically be called each time a decorated
# object is cloned/created
def __call__(self):
# Create an instance of the class here so a unique object can be
# sent back to the constructor
self.instance = self.cls()
# Assign the private functions back to the unique class
# (which is the whole point of this decorator)
self.instance.Clone = self._clone_func
self.instance.Copy = self._copy_func
# Finally, send the unique object back to the object's constructor
return self.instance
@Prototype
class Concrete:
def __init__(self):
# Test value to see if objects are independently generated as
# well as if they properly copy from one another
self.somevar = 0
@Prototype
class another:
def __init__(self):
self.somevar = 50
if __name__ == '__main__':
print "Creating A"
a = Concrete()
print "Cloning A to B"
b = a.Clone()
print "A and B somevars"
print a.somevar
print b.somevar
print "Changing A somevar to 10..."
a.somevar = 10
print "A and B somevars"
print a.somevar
print b.somevar
print "Creating another kind of class as C"
c = another()
print "Cloning C to D"
d = c.Clone()
print "Changing C somevar to 100"
c.somevar = 100
print "C and D somevars"
print c.somevar
print d.somevar
Output:
Creating A Cloning A to B A and B somevars 0 0 Changing A somevar to 10... A and B somevars 10 0 Creating another kind of class as C Cloning C to D Changing C somevar to 100 C and D somevars 100 50
Proxy
[edit | edit source]
Control the access to an object.
The example creates first an interface against which the pattern creates the classes. This interface contains only one method to display the image, called displayImage()
, that has to be coded by all classes implementing it.
The proxy class ProxyImage
is running on another system than the real image class itself and can represent the real image RealImage
over there. The image information is accessed from the disk. Using the proxy pattern, the code of the ProxyImage
avoids multiple loading of the image, accessing it from the other system in a memory-saving manner.
interface ICar
{
void DriveCar() ;
}
// Real Object
public class Car : ICar
{
public void DriveCar()
{
Console.WriteLine("Car has been driven!");
}
}
// Proxy Object
public class ProxyCar : ICar
{
private Driver driver;
private ICar realCar;
public ProxyCar(Driver driver)
{
this.driver = driver;
this.realCar = new Car();
}
public void DriveCar()
{
if (driver.Age < 16)
Console.WriteLine("Sorry, the driver is too young to drive.");
else
this.realCar.DriveCar();
}
}
public class Driver
{
public int Age { get; set; }
public Driver(int age)
{
this.Age = age;
}
}
// How to use above Proxy class?
private void btnProxy_Click(object sender, EventArgs e)
{
ICar car = new ProxyCar(new Driver(15));
car.DriveCar();
car = new ProxyCar(new Driver(25));
car.DriveCar();
}
Output
Sorry, the driver is too young to drive. Car has been driven!
Notes:
- A proxy may hide information about the real object to the client.
- A proxy may perform optimization like on demand loading.
- A proxy may do additional house-keeping job like audit tasks.
- Proxy design pattern is also known as surrogate design pattern.
Another example:
using System;
namespace Proxy
{
class Program
{
interface IImage
{
void Display();
}
class RealImage : IImage
{
public RealImage(string fileName)
{
FileName = fileName;
LoadFromFile();
}
private void LoadFromFile()
{
Console.WriteLine("Loading " + FileName);
}
public String FileName { get; private set; }
public void Display()
{
Console.WriteLine("Displaying " + FileName);
}
}
class ProxyImage : IImage
{
public ProxyImage(string fileName)
{
FileName = fileName;
}
public String FileName { get; private set; }
private IImage image;
public void Display()
{
if (image == null)
image = new RealImage(FileName);
image.Display();
}
}
static void Main(string[] args)
{
IImage image = new ProxyImage("HiRes_Image");
for (int i = 0; i < 10; i++)
image.Display();
}
}
}
The program's output is:
Loading HiRes_Image Displaying HiRes_Image Displaying HiRes_Image Displaying HiRes_Image Displaying HiRes_Image Displaying HiRes_Image Displaying HiRes_Image Displaying HiRes_Image Displaying HiRes_Image Displaying HiRes_Image Displaying HiRes_Image
#include <iostream>
#include <memory>
class ICar {
public:
virtual ~ICar() { std::cout << "ICar destructor!\n"; }
virtual void DriveCar() = 0;
};
class Car : public ICar {
public:
void DriveCar() override { std::cout << "Car has been driven!\n"; }
};
class ProxyCar : public ICar {
public:
ProxyCar(int driver_age) : driver_age_(driver_age) {}
void DriveCar() override {
if (driver_age_ > 16) {
real_car_->DriveCar();
} else {
std::cout << "Sorry, the driver is too young to drive.\n";
}
}
private:
std::unique_ptr<ICar> real_car_ = std::make_unique<Car>();
int driver_age_;
};
int main() {
std::unique_ptr<ICar> car = std::make_unique<ProxyCar>(16);
car->DriveCar();
car = std::make_unique<ProxyCar>(25);
car->DriveCar();
}
abstract class AbstractCar
abstract def drive
end
class Car < AbstractCar
def drive
puts "Car has been driven!"
end
end
class Driver
getter age : Int32
def initialize(@age)
end
end
class ProxyCar < AbstractCar
private getter driver : Driver
private getter real_car : AbstractCar
def initialize(@driver)
@real_car = Car.new
end
def drive
if driver.age <= 16
puts "Sorry, the driver is too young to drive."
else
@real_car.drive
end
end
end
# Program
driver = Driver.new(16)
car = ProxyCar.new(driver)
car.drive
driver = Driver.new(25)
car = ProxyCar.new(driver)
car.drive
Output
Sorry, the driver is too young to drive. Car has been driven!
// Proxy Design pattern
unit DesignPattern.Proxy;
interface
type
// Car Interface
ICar = interface
procedure DriveCar;
end;
// TCar class, implementing ICar
TCar = Class(TInterfacedObject, ICar)
class function New: ICar;
procedure DriveCar;
End;
// Driver Interface
IDriver = interface
function Age: Integer;
end;
// TDriver Class, implementing IDriver
TDriver = Class(TInterfacedObject, IDriver)
private
FAge: Integer;
public
constructor Create(Age: Integer); Overload;
class function New(Age: Integer): IDriver;
function Age: Integer;
End;
// Proxy Object
TProxyCar = Class(TInterfacedObject, ICar)
private
FDriver: IDriver;
FRealCar: ICar;
public
constructor Create(Driver: IDriver); Overload;
class function New(Driver: IDriver): ICar;
procedure DriveCar;
End;
implementation
{ TCar Implementation }
class function TCar.New: ICar;
begin
Result := Create;
end;
procedure TCar.DriveCar;
begin
WriteLn('Car has been driven!');
end;
{ TDriver Implementation }
constructor TDriver.Create(Age: Integer);
begin
inherited Create;
FAge := Age;
end;
class function TDriver.New(Age: Integer): IDriver;
begin
Result := Create(Age);
end;
function TDriver.Age: Integer;
begin
Result := FAge;
end;
{ TProxyCar Implementation }
constructor TProxyCar.Create(Driver: IDriver);
begin
inherited Create;
Self.FDriver := Driver;
Self.FRealCar := TCar.Create AS ICar;
end;
class function TProxyCar.New(Driver: IDriver): ICar;
begin
Result := Create(Driver);
end;
procedure TProxyCar.DriveCar;
begin
if (FDriver.Age <= 16)
then WriteLn('Sorry, the driver is too young to drive.')
else FRealCar.DriveCar();
end;
end.
Usage
program Project1;
{$APPTYPE Console}
uses
DesignPattern.Proxy in 'DesignPattern.Proxy.pas';
begin
TProxyCar.New(TDriver.New(16)).DriveCar;
TProxyCar.New(TDriver.New(25)).DriveCar;
end.
Output
Sorry, the driver is too young to drive. Car has been driven!
The following Java example illustrates the "virtual proxy" pattern. The ProxyImage
class is used to access a remote method.
The example creates first an interface against which the pattern creates the classes. This interface contains only one method to display the image, called displayImage()
, that has to be coded by all classes implementing it.
The proxy class ProxyImage
is running on another system than the real image class itself and can represent the real image RealImage
over there. The image information is accessed from the disk. Using the proxy pattern, the code of the ProxyImage
avoids multiple loading of the image, accessing it from the other system in a memory-saving manner. The lazy loading demonstrated in this example is not part of the proxy pattern, but is merely an advantage made possible by the use of the proxy.
interface Image {
public void displayImage();
}
// On System A
class RealImage implements Image {
private final String filename;
/**
* Constructor
* @param filename
*/
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
/**
* Loads the image from the disk
*/
private void loadImageFromDisk() {
System.out.println("Loading " + filename);
}
/**
* Displays the image
*/
public void displayImage() {
System.out.println("Displaying " + filename);
}
}
// On System B
class ProxyImage implements Image {
private final String filename;
private RealImage image;
/**
* Constructor
* @param filename
*/
public ProxyImage(String filename) {
this.filename = filename;
}
/**
* Displays the image
*/
public void displayImage() {
if (image == null) {
image = new RealImage(filename);
}
image.displayImage();
}
}
class ProxyExample {
/**
* Test method
*/
public static void main(final String[] arguments) {
Image image1 = new ProxyImage("HiRes_10MB_Photo1");
Image image2 = new ProxyImage("HiRes_10MB_Photo2");
image1.displayImage(); // loading necessary
image1.displayImage(); // loading unnecessary
image2.displayImage(); // loading necessary
image2.displayImage(); // loading unnecessary
image1.displayImage(); // loading unnecessary
}
}
Output
Loading HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Loading HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo1
// Driver class
class Driver {
constructor (age) {
this.age = age
}
}
// Car class
class Car {
drive () {
console.log('Car has been driven!')
}
}
// Proxy car class
class ProxyCar {
constructor (driver) {
this.car = new Car()
this.driver = driver
}
drive () {
if (this.driver.age <= 16) {
console.log('Sorry, the driver is too young to drive.')
} else {
this.car.drive()
}
}
}
// Run program
const driver = new Driver(16)
const car = new ProxyCar(driver)
car.drive()
const driver2 = new Driver(25)
const car2 = new ProxyCar(driver2)
car2.drive()
Output
Sorry, the driver is too young to drive. Car has been driven!
More advanced proxies involve the Proxy
object, which can intercept and redefine fundamental operations such as accessing properties. The handler functions in this case are sometimes called traps.[1]
<?php
interface Image
{
public function displayImage();
}
// On System A
class RealImage implements Image
{
private string $filename = null;
public function __construct(string $filename)
{
$this->filename = $filename;
$this->loadImageFromDisk();
}
/**
* Loads the image from the disk
*/
private function loadImageFromDisk()
{
echo "Loading {$this->filename}" . \PHP_EOL;
}
/**
* Displays the image
*/
public function displayImage()
{
echo "Displaying {$this->filename}" . \PHP_EOL;
}
}
// On System B
class ProxyImage implements Image
{
private ?Image $image = null;
private string $filename = null;
public function __construct(string $filename)
{
$this->filename = $filename;
}
/**
* Displays the image
*/
public function displayImage()
{
if ($this->image === null) {
$this->image = new RealImage($this->filename);
}
$this->image->displayImage();
}
}
$image1 = new ProxyImage("HiRes_10MB_Photo1");
$image2 = new ProxyImage("HiRes_10MB_Photo2");
$image1->displayImage(); // Loading necessary
$image1->displayImage(); // Loading unnecessary
$image2->displayImage(); // Loading necessary
$image2->displayImage(); // Loading unnecessary
$image1->displayImage(); // Loading unnecessary
Output
Loading HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Displaying HiRes_10MB_Photo1 Loading HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo2 Displaying HiRes_10MB_Photo1
"""
Proxy pattern example.
"""
from abc import ABCMeta, abstractmethod
NOT_IMPLEMENTED = "You should implement this."
class AbstractCar:
__metaclass__ = ABCMeta
@abstractmethod
def drive(self):
raise NotImplementedError(NOT_IMPLEMENTED)
class Car(AbstractCar):
def drive(self) -> None:
print("Car has been driven!")
class Driver:
def __init__(self, age: int) -> None:
self.age = age
class ProxyCar(AbstractCar):
def __init__(self, driver) -> None:
self.car = Car()
self.driver = driver
def drive(self) -> None:
if self.driver.age <= 16:
print("Sorry, the driver is too young to drive.")
else:
self.car.drive()
driver = Driver(16)
car = ProxyCar(driver)
car.drive()
driver = Driver(25)
car = ProxyCar(driver)
car.drive()
Output
Sorry, the driver is too young to drive. Car has been driven!
trait ICar {
fn drive(&self);
}
struct Car {}
impl ICar for Car {
fn drive(&self) {
println!("Car has been driven!");
}
}
impl Car {
fn new() -> Car {
Car {}
}
}
struct ProxyCar<'a> {
real_car: &'a ICar,
driver_age: i32,
}
impl<'a> ICar for ProxyCar<'a> {
fn drive(&self) {
if self.driver_age > 16 {
self.real_car.drive();
} else {
println!("Sorry, the driver is too young to drive.")
}
}
}
impl<'a> ProxyCar<'a> {
fn new(driver_age: i32, other_car: &'a ICar) -> ProxyCar {
ProxyCar {
real_car: other_car,
driver_age: driver_age,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_underage() {
let car = Car::new();
let proxy_car = ProxyCar::new(16, &car);
proxy_car.drive();
}
#[test]
fn test_can_drive() {
let car = Car::new();
let proxy_car = ProxyCar::new(17, &car);
proxy_car.drive();
}
}
Output
Sorry, the car is to young for you to drive. Car has been driven!
Singleton
[edit | edit source]
The term Singleton refers to an object that can be instantiated only once. Use the Singleton Design pattern if:
- You need global access to a resource, like logging ...
- You need only one instance of a utility class, do not want to create lots of objects.
In some applications, it is appropriate to enforce a single instance of an object, for example: window managers, print spoolers, database access, and filesystems.
Refresh Java object creation
In programming languages like Java, you have to create an instance of an object type (commonly called a Class) to use it throughout the code. Let's take for example this code:
Animal dog; // Declaring the object type
dog = new Animal(); // Instantiating an object
This can also be written in a single line to save space.
Animal dog = new Animal(); // Both declaring and instantiating
At times, you need more than one instance of the same object type. You can create multiple instances of the same object type. Take for instance:
Animal dog = new Animal();
Animal cat = new Animal();
Now that I have two instances of the same object type, I can use both dog
and cat
instances separately in my program. Any changes to dog
would not effect the cat
instance because both of them have been created in separate memory spaces. To see whether these objects actually are different we do something like this:
System.out.println(dog.equals(cat)); // output: false
The code returns false
because both the objects are different. Contrary to this behavior, the Singleton behaves differently. A Singleton object type can not be instantiated yet you can obtain an instance of the object type. Let us create a normal object using Java.
class NormalObject {
public NormalObject() {
}
}
What we have done here is that we have created a class (object type) to identify our object. Within the braces of the class is a single method with the same name as that of the class (methods can be identified by the usage of parentheses at the end of their names). Methods that have the same name as that of the class and that do not have a return type are called Constructors in OOP syntax. To create an instance of the class, the code can not be much simpler.
class TestHarness {
public static void main(String[] args) {
NormalObject object = new NormalObject();
}
}
Note that to encourage the instantiation of this object, the constructor is called. The constructor as in this case can be called outside the class paranthesis and into another class definition because it is declared a public accessor while creating the Constructor in the above example.
- Creating singleton object
Now we will create the Singleton object. You just have to change one thing to adhere to the Singleton design pattern: Make your Constructor's accessor private.
class SingletonObject {
private SingletonObject() {
}
}
Notice the constructor's accessor. This time around it has been declared private. Just by changing it to private, you have applied a great change to your object type. Now you can not instantiate the object type. Go ahead try out the following code.
class TestHarness {
public static void main(String[] args) {
SingletonObject object = new SingletonObject();
}
}
The code returns an error because private class members can not be accessed from outside the class itself and in another class. This way you have disabled the instantiation process for an object type. However, you have to find a way of obtaining an instance of the object type. Let's do some changes here.
class SingletonObject {
private static SingletonObject object;
private SingletonObject() {
// Instantiate the object.
}
public static SingletonObject getInstance() {
if (object == null) {
object = new SingletonObject(); // Create the object for the first and last time
}
return object;
}
}
The changes involve adding a static class field called object
and a public static
method that can be accessible outside the scope of the class by using the name of the Class. To see how we can obtain the instance, lets code:
class TestHarness {
public static void main(String[] args) {
SingletonObject object = SingletonObject.getInstance();
}
}
This way you control the creation of objects derived from your class. But we have still not unearthed the final and interesting part of the whole process. Try getting multiple objects and see what happens.
class TestHarness {
public static void main(String[] args) {
SingletonObject object1 = SingletonObject.getInstance();
SingletonObject object2 = SingletonObject.getInstance();
}
}
Unlike multiple instances of normal object types, multiple instances of a Singleton are all actually the same object instance. To validate the concept in Java, we try:
System.out.println(object1.equals(object2)); // output: true
The code returns true
because both object declarations are actually referring to the same object. So, in summarizing the whole concept, a Singleton can be defined as an object that can not be instantiated more than once. Typically it is obtained using a static custom implementation.
Singleton & Multi Threading
Java uses multi threading concept, to run/execute any program. Consider the class SingletonObject discussed above. Call to the method getInstance() by more than one thread at any point of time might create two instances of SingletonObject thus defeating the whole purpose of creating the singleton pattern. To make singelton thread safe, we have three options:
1. Synchronize the method getInstance()
, which would look like:
// Only one thread can enter and stay in this method at a time
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
Synchronizing the method guarantees that the method will never be called twice at the same time. The problem with the above code is that 'synchronization' is expensive. 'Synchronization' checks will occur every time the function is called. Therefore, the above code should not be the first option. 2. Another approach would be to create a singleton instance as shown below:
class SingletonObject {
private volatile static SingletonObject object;
private final static Object lockObj = new Object(); // Use for locking
private SingletonObject() {
// Exists only to avoid instantiation.
}
public static SingletonObject getInstance() {
if (object != null) {
return object;
} else {
// Start a synchronized block, only one thread can enter and stay in the block one at a time
synchronized(lockObj) {
if (object == null) {
object = new SingletonObject();
}
} // End of synchronized block
return object;
}
}
}
The above code will be much faster; once the singleton instance is created no synchronization is needed. It just returns the same instance reference. 3. Use static initialization block to create the instance. The JVM makes sure that the static block is executed once when the class is loaded.
class SingletonObject {
public final static SingletonObject object;
static {
...
object = new SingletonObject();
}
private SingletonObject() {
// Exists only to avoid instantiation.
}
public static SingletonObject getInstance() {
return object;
}
}
Examples
In Java, the class java.lang.Runtime
is a singleton. Its constructor is protected and you can get an instance by calling the getRuntime()
method.
Cost
Beware of this design pattern! It creates the same issues than the global variables in procedural programming so it can be hard to debug.
Creation
It can be expensive. You may have to refactor all the instantiations of the class, unless the class is new.
Maintenance
There is no additional cost.
Removal
This pattern can be easily removed as automatic refactoring operations can easily remove its existence.
Advises
- Name the method
getInstance()
to indicate the use of the pattern to the other developers. - Use this design pattern for frozen data like configuration or external data. You will not have debugging issues.
Implementation
The Scala programming language supports Singleton objects out-of-the-box. The 'object' keyword creates a class and also defines a singleton object of that type. Singletons are declared just like classes except "object" replaces the keyword "class".
object MySingleton {
println("Creating the singleton")
val i : Int = 0
}
Traditional simple way using synchronization
This solution is thread-safe without requiring special language constructs:
public class Singleton {
private volatile static Singleton singleton; // volatile is needed so that multiple thread can reconcile the instance
private Singleton(){}
public static Singleton getSingleton() { // synchronized keyword has been removed from here
if (singleton == null) { // needed because once there is singleton available no need to aquire monitor again & again as it is costly
synchronized(Singleton.class) {
if (singleton == null) { // this is needed if two threads are waiting at the monitor at the time when singleton was getting instantiated
singleton = new Singleton();
}
}
}
return singleton;
}
}
Initialization on Demand Holder Idiom
This technique is as lazy as possible, and works in all known versions of Java. It takes advantage of language guarantees about class initialization, and will therefore work correctly in all Java-compliant compilers and virtual machines. The nested class is referenced when getInstance() is called making this solution thread-safe without requiring special language constructs.
public class Singleton {
// Private constructor prevents instantiation from other classes
private Singleton() {}
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
The Enum-way
In the second edition of his book "Effective Java" Joshua Bloch claims that "a single-element enum type is the best way to implement a singleton" for any Java that supports enums. The use of an enum is very easy to implement and has no drawbacks regarding serializable objects, which have to be circumvented in the other ways.
public enum Singleton {
INSTANCE;
}
Singleton pattern in D programming language
import std.stdio;
import std.string;
class Singleton(T) {
private static T instance;
public static T opCall() {
if(instance is null) {
instance = new T;
}
return instance;
}
}
class Foo {
public this() {
writefln("Foo Constructor");
}
}
void main(){
Foo a = Singleton!(Foo)();
Foo b = Singleton!(Foo)();
}
Or in this manner
// this class should be in a package to make private this() not visible
class Singleton {
private static Singleton instance;
public static Singleton opCall() {
if(instance is null) {
instance = new Singleton();
}
return instance;
}
private this() {
writefln("Singleton constructor");
}
}
void main(){
Singleton a = Singleton();
Singleton b = Singleton();
}
Singleton pattern in PHP 5:
<?php
class Singleton {
// object instance
private static $instance;
// The protected construct prevents instantiating the class externally. The construct can be
// empty, or it can contain additional instructions...
// This should also be final to prevent extending objects from overriding the constructor with
// public.
protected final function __construct() {
...
}
// The clone and wakeup methods prevents external instantiation of copies of the Singleton class,
// thus eliminating the possibility of duplicate objects. The methods can be empty, or
// can contain additional code (most probably generating error messages in response
// to attempts to call).
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Deserializing is not allowed.', E_USER_ERROR);
}
// This method must be static, and must return an instance of the object if the object
// does not already exist.
public static function getInstance() {
if (!self::$instance instanceof self) {
self::$instance = new self;
}
return self::$instance;
}
// One or more public methods that grant access to the Singleton object, and its private
// methods and properties via accessor methods.
public function doAction() {
...
}
}
// usage
Singleton::getInstance()->doAction();
?>
Private constructors are not available in ActionScript 3.0 - which prevents the use of the ActionScript 2.0 approach to the Singleton Pattern. Many different AS3 Singleton implementations have been published around the web.
package {
public class Singleton {
private static var _instance:Singleton = new Singleton();
public function Singleton () {
if (_instance){
throw new Error(
"Singleton can only be accessed through Singleton.getInstance()"
);
}
}
public static function getInstance():Singleton {
return _instance;
}
}
}
A common way to implement a singleton in Objective-C is the following:
@interface MySingleton : NSObject
{
}
+ (MySingleton *)sharedSingleton;
@end
@implementation MySingleton
+ (MySingleton *)sharedSingleton
{
static MySingleton *sharedSingleton;
@synchronized(self)
{
if (!sharedSingleton)
sharedSingleton = [[MySingleton alloc] init];
return sharedSingleton;
}
}
@end
If thread-safety is not required, the synchronization can be left out, leaving the +sharedSingleton
method like this:
+ (MySingleton *)sharedSingleton
{
static MySingleton *sharedSingleton;
if (!sharedSingleton)
sharedSingleton = [[MySingleton alloc] init];
return sharedSingleton;
}
This pattern is widely used in the Cocoa frameworks (see for instance, NSApplication
, NSColorPanel
, NSFontPanel
or NSWorkspace
, to name but a few).
Some may argue that this is not, strictly speaking, a Singleton, because it is possible to allocate more than one instance of the object. A common way around this is to use assertions or exceptions to prevent this double allocation.
@interface MySingleton : NSObject
{
}
+ (MySingleton *)sharedSingleton;
@end
@implementation MySingleton
static MySingleton *sharedSingleton;
+ (MySingleton *)sharedSingleton
{
@synchronized(self)
{
if (!sharedSingleton)
[[MySingleton alloc] init];
return sharedSingleton;
}
}
+(id)alloc
{
@synchronized(self)
{
NSAssert(sharedSingleton == nil, @"Attempted to allocate a second instance of a singleton.");
sharedSingleton = [super alloc];
return sharedSingleton;
}
}
@end
There are alternative ways to express the Singleton pattern in Objective-C, but they are not always as simple or as easily understood, not least because they may rely on the -init
method returning an object other than self
. Some of the Cocoa "Class Clusters" (e.g. NSString
, NSNumber
) are known to exhibit this type of behaviour.
Note that @synchronized
is not available in some Objective-C configurations, as it relies on the NeXT/Apple runtime. It is also comparatively slow, because it has to look up the lock based on the object in parentheses.
The simplest of all is:
public class Singleton
{
// The combination of static and readonly makes the instantiation
// thread safe. Plus the constructor being protected (it can be
// private as well), makes the class sure to not have any other
// way to instantiate this class than using this member variable.
public static readonly Singleton Instance = new Singleton();
// Protected constructor is sufficient to avoid other instantiation
// This must be present otherwise the compiler provides a default
// public constructor
//
protected Singleton()
{
}
}
This example is thread-safe with lazy initialization.
/// Class implements singleton pattern.
public class Singleton
{
//Use Lazy<T> to lazily initialize the class and provide thread-safe access
private static readonly Lazy<Singleton> _lazyInstance = new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance
{
get { return _lazyInstance.Value; }
}
private Singleton() { }
}
Example in C# 2.0 (thread-safe with lazy initialization) Note: This is not a recommended implementation because "TestClass" has a default public constructor, and that violates the definition of a Singleton. A proper Singleton must never be instantiable more than once. More about generic singleton solution in C#: http://www.c-sharpcorner.com/UploadFile/snorrebaard/GenericSingleton11172008110419AM/GenericSingleton.aspx
/// Parent for singleton
/// <typeparam name="T">Singleton class</typeparam>
public class Singleton<T> where T : class, new()
{
protected Singleton() { }
private sealed class SingletonCreator<S> where S : class, new()
{
private static readonly S instance = new S();
//explicit static constructor to disable beforefieldinit
static SingletonCreator() { }
public static S CreatorInstance
{
get { return instance; }
}
}
public static T Instance
{
get { return SingletonCreator<T>.CreatorInstance; }
}
}
/// Concrete Singleton
public class TestClass : Singleton<TestClass>
{
public string TestProc()
{
return "Hello World";
}
}
// Somewhere in the code
.....
TestClass.Instance.TestProc();
.....
As described by James Heyworth in a paper presented to the Canberra PC Users Group Delphi SIG on 11/11/1996, there are several examples of the Singleton pattern built into the Delphi Visual Component Library. This unit demonstrates the techniques that were used in order to create both a Singleton component and a Singleton object:
unit Singletn;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs;
type
TCSingleton = class(TComponent)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
TOSingleton = class(TObject)
public
constructor Create;
destructor Destroy; override;
end;
var
Global_CSingleton: TCSingleton;
Global_OSingleton: TOSingleton;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Design Patterns', [TCSingleton]);
end;
{ TCSingleton }
constructor TCSingleton.Create(AOwner: TComponent);
begin
if Global_CSingleton <> nil then
{NB could show a message or raise a different exception here}
Abort
else begin
inherited Create(AOwner);
Global_CSingleton := Self;
end;
end;
destructor TCSingleton.Destroy;
begin
if Global_CSingleton = Self then
Global_CSingleton := nil;
inherited Destroy;
end;
{ TOSingleton }
constructor TOSingleton.Create;
begin
if Global_OSingleton <> nil then
{NB could show a message or raise a different exception here}
Abort
else
Global_OSingleton := Self;
end;
destructor TOSingleton.Destroy;
begin
if Global_OSingleton = Self then
Global_OSingleton := nil;
inherited Destroy;
end;
procedure FreeGlobalObjects; far;
begin
if Global_CSingleton <> nil then
Global_CSingleton.Free;
if Global_OSingleton <> nil then
Global_OSingleton.Free;
end;
begin
AddExitProc(FreeGlobalObjects);
end.
The desired properties of the Singleton pattern can most simply be encapsulated in Python by defining a module, containing module-level variables and functions. To use this modular Singleton, client code merely imports the module to access its attributes and functions in the normal manner. This sidesteps many of the wrinkles in the explicitly-coded versions below, and has the singular advantage of requiring zero lines of code to implement. According to influential Python programmer Alex Martelli, The Singleton design pattern (DP) has a catchy name, but the wrong focus—on identity rather than on state. The Borg design pattern has all instances share state instead. A rough consensus in the Python community is that sharing state among instances is more elegant, at least in Python, than is caching creation of identical instances on class initialization. Coding shared state is nearly transparent:
class Borg:
__shared_state = {}
def __init__(self):
self.__dict__ = self.__shared_state
# and whatever else is needed in the class -- that's all!
But with the new style class, this is a better solution, because only one instance is created:
class Singleton (object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, 'self'):
cls.self = object.__new__(cls)
return cls.self
#Usage
mySingleton1 = Singleton()
mySingleton2 = Singleton()
#mySingleton1 and mySingleton2 are the same instance.
assert mySingleton1 is mySingleton2
Two caveats:
- The __init__-method is called every time Singleton() is called, unless cls.__init__ is set to an empty function.
- If it is needed to inherit from the Singleton-class, instance should probably be a dictionary belonging explicitly to the Singleton-class.
class InheritableSingleton (object):
instances = {}
def __new__(cls, *args, **kwargs):
if InheritableSingleton.instances.get(cls) is None:
cls.__original_init__ = cls.__init__
InheritableSingleton.instances[cls] = object.__new__(cls, *args, **kwargs)
elif cls.__init__ == cls.__original_init__:
def nothing(*args, **kwargs):
pass
cls.__init__ = nothing
return InheritableSingleton.instances[cls]
To create a singleton that inherits from a non-singleton, multiple inheritance must be used.
class Singleton (NonSingletonClass, object):
instance = None
def __new__(cls, *args, **kargs):
if cls.instance is None:
cls.instance = object.__new__(cls, *args, **kargs)
return cls.instance
Be sure to call the NonSingletonClass's __init__ function from the Singleton's __init__ function. A more elegant approach using metaclasses was also suggested.
class SingletonType(type):
def __call__(cls):
if getattr(cls, '__instance__', None) is None:
instance = cls.__new__(cls)
instance.__init__()
cls.__instance__ = instance
return cls.__instance__
# Usage
class Singleton(object):
__metaclass__ = SingletonType
def __init__(self):
print '__init__:', self
class OtherSingleton(object):
__metaclass__ = SingletonType
def __init__(self):
print 'OtherSingleton __init__:', self
# Tests
s1 = Singleton()
s2 = Singleton()
assert s1
assert s2
assert s1 is s2
os1 = OtherSingleton()
os2 = OtherSingleton()
assert os1
assert os2
assert os1 is os2
In Perl version 5.10 or newer a state variable can be used.
package MySingletonClass;
use strict;
use warnings;
use 5.010;
sub new {
my ($class) = @_;
state $the_instance;
if (! defined $the_instance) {
$the_instance = bless { }, $class;
}
return $the_instance;
}
In older Perls, just use a global variable.
package MySingletonClass;
use strict;
use warnings;
my $THE_INSTANCE;
sub new {
my ($class) = @_;
if (! defined $THE_INSTANCE) {
$THE_INSTANCE = bless { }, $class;
}
return $THE_INSTANCE;
}
If Moose is used, there is the MooseX::Singleton extension module.
In Ruby, just include the Singleton module from the standard library into the class.
require 'singleton'
class Example
include Singleton
end
# Access to the instance:
Example.instance
In ABAP Objects, to make instantiation private, add an attribute of type ref to the class, and a static method to control instantiation.
program pattern_singleton. *********************************************************************** * Singleton * ========= * Intent * * Ensure a class has only one instance, and provide a global point * of access to it. *********************************************************************** class lcl_Singleton definition create private. public section. class-methods: get_Instance returning value(Result) type ref to lcl_Singleton. private section. class-data: fg_Singleton type ref to lcl_Singleton. endclass. class lcl_Singleton implementation. method get_Instance. if ( fg_Singleton is initial ). create object fg_Singleton. endif. Result = fg_Singleton. endmethod. endclass.
State
[edit | edit source]
Allow an object to alter its behaviour when its internal state changes. The object will appear to change its class.
#include <iostream>
using namespace std;
class Machine
{
class State *current;
public:
Machine();
void setCurrent(State *s)
{
current = s;
}
void on();
void off();
};
class State
{
public:
virtual void on(Machine *m)
{
cout << " already ON\n";
}
virtual void off(Machine *m)
{
cout << " already OFF\n";
}
};
void Machine::on()
{
current->on(this);
}
void Machine::off()
{
current->off(this);
}
class ON: public State
{
public:
ON()
{
cout << " ON-ctor ";
};
~ON()
{
cout << " dtor-ON\n";
};
void off(Machine *m);
};
class OFF: public State
{
public:
OFF()
{
cout << " OFF-ctor ";
};
~OFF()
{
cout << " dtor-OFF\n";
};
void on(Machine *m)
{
cout << " going from OFF to ON";
m->setCurrent(new ON());
delete this;
}
};
void ON::off(Machine *m)
{
cout << " going from ON to OFF";
m->setCurrent(new OFF());
delete this;
}
Machine::Machine()
{
current = new OFF();
cout << '\n';
}
int main()
{
void(Machine:: *ptrs[])() =
{
Machine::off, Machine::on
};
Machine fsm;
int num;
while (1)
{
cout << "Enter 0/1: ";
cin >> num;
(fsm. *ptrs[num])();
}
}
using System;
class MainApp
{
static void Main()
{
// Setup context in a state
Context c = new Context(new ConcreteStateA());
// Issue requests, which toggles state
c.Request();
c.Request();
c.Request();
c.Request();
// Wait for user
Console.Read();
}
}
// "State"
abstract class State
{
public abstract void Handle(Context context);
}
// "ConcreteStateA"
class ConcreteStateA : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateB();
}
}
// "ConcreteStateB"
class ConcreteStateB : State
{
public override void Handle(Context context)
{
context.State = new ConcreteStateA();
}
}
// "Context"
class Context
{
private State state;
// Constructor
public Context(State state)
{
this.State = state;
}
// Property
public State State
{
get{ return state; }
set
{
state = value;
Console.WriteLine("State: " +
state.GetType().Name);
}
}
public void Request()
{
state.Handle(this);
}
}
The state interface and two implementations. The state's method has a reference to the context object and is able to change its state.
interface Statelike {
/**
* Writer method for the state name.
* @param STATE_CONTEXT
* @param NAME
*/
void writeName(final StateContext STATE_CONTEXT, final String NAME);
}
class StateA implements Statelike {
/* (non-Javadoc)
* @see state.Statelike#writeName(state.StateContext, java.lang.String)
*/
@Override
public void writeName(final StateContext STATE_CONTEXT, final String NAME) {
System.out.println(NAME.toLowerCase());
STATE_CONTEXT.setState(new StateB());
}
}
class StateB implements Statelike {
/** State counter */
private int count = 0;
/* (non-Javadoc)
* @see state.Statelike#writeName(state.StateContext, java.lang.String)
*/
@Override
public void writeName(final StateContext STATE_CONTEXT, final String NAME) {
System.out.println(NAME.toUpperCase());
// Change state after StateB's writeName() gets invoked twice
++count;
if (count > 1) {
STATE_CONTEXT.setState(new StateA());
}
}
}
The context class has a state variable that it instantiates in an initial state, in this case StateA
. In its method, it uses the corresponding methods of the state object.
public class StateContext {
private Statelike myState;
/**
* Standard constructor
*/
public StateContext() {
setState(new StateA());
}
/**
* Setter method for the state.
* Normally only called by classes implementing the State interface.
* @param NEW_STATE
*/
public void setState(final Statelike NEW_STATE) {
myState = NEW_STATE;
}
/**
* Writer method
* @param NAME
*/
public void writeName(final String NAME) {
myState.writeName(this, NAME);
}
}
The test below shows also the usage:
public class TestClientState {
public static void main(String[] args) {
final StateContext SC = new StateContext();
SC.writeName("Monday");
SC.writeName("Tuesday");
SC.writeName("Wednesday");
SC.writeName("Thursday");
SC.writeName("Friday");
SC.writeName("Saturday");
SC.writeName("Sunday");
}
}
According to the above code, the output of main() from TestClientState should be:
monday TUESDAY WEDNESDAY thursday FRIDAY SATURDAY sunday
use strict;
use warnings;
package State;
# base state, shared functionality
use base qw{Class::Accessor};
# scan the dial to the next station
sub scan {
my $self = shift;
printf "Scanning... Station is %s %s\n",
$self->{stations}[$self->{pos}], $self->{name};
$self->{pos}++;
if ($self->{pos} >= @{$self->{stations}}) {
$self->{pos} = 0
}
}
package AmState;
our @ISA = qw(State);
AmState->mk_accessors(qw(radio pos name));
use Scalar::Util 'weaken';
sub new {
my ($class, $radio) = @_;
my $self;
@$self{qw(stations pos name radio)} =
([1250,1380,1510], 0, 'AM', $radio);
# make circular reference weak
weaken $self->{radio};
bless $self, $class;
}
sub toggle_amfm {
my $self = shift;
print "Switching to FM\n";
$self->radio->state( $self->radio->fmstate );
}
package FmState;
our @ISA = qw(State);
FmState->mk_accessors(qw(radio pos name));
use Scalar::Util 'weaken';
sub new {
my ($class, $radio) = @_;
my $self;
@$self{qw(stations pos name radio)} =
([81.3,89.3,103.9], 0, 'FM', $radio);
# make circular reference weak
weaken $self->{radio};
bless $self, $class;
}
sub toggle_amfm {
my $self = shift;
print "Switching to AM\n";
$self->radio->state( $self->radio->amstate );
}
package Radio;
# this is a radio, it has a scan button and a am/fm toggle
use base qw{Class::Accessor};
Radio->mk_accessors(qw(amstate fmstate state));
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
@$self{ 'amstate', 'fmstate' }
= ( AmState->new($self), FmState->new($self), );
$self->state( $self->amstate );
$self;
}
sub toggle_amfm {
shift->state->toggle_amfm;
}
sub scan {
shift->state->scan;
}
package main;
# test out our radio
sub main {
my $radio = Radio->new;
my @actions = (
('scan')x2,
('toggle_amfm'),
('scan')x2
)x2;
for my $action (@actions) {
$radio->$action;
}
exit;
}
main();
import itertools
"""Implementation of the state pattern"""
class State(object):
"""Base state. This is to share functionality"""
def scan(self):
"""Scan the dial to the next station"""
print "Scanning... Station is", self.stations.next(), self.name
class AmState(State):
def __init__(self, radio):
self.radio = radio
self.stations = itertools.cycle(["1250", "1380", "1510"])
self.name = "AM"
def toggle_amfm(self):
print "Switching to FM"
self.radio.state = self.radio.fmstate
class FmState(State):
def __init__(self, radio):
self.radio = radio
self.stations = itertools.cycle(["81.3", "89.1", "103.9"])
self.name = "FM"
def toggle_amfm(self):
print "Switching to AM"
self.radio.state = self.radio.amstate
class Radio(object):
"""A radio.
It has a scan button, and an AM/FM toggle switch."""
def __init__(self):
"""We have an AM state and an FM state"""
self.amstate = AmState(self)
self.fmstate = FmState(self)
self.state = self.amstate
def toggle_amfm(self):
self.state.toggle_amfm()
def scan(self):
self.state.scan()
def main():
''' Test our radio out '''
radio = Radio()
actions = ([radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2) * 2
for action in actions:
action()
if __name__ == '__main__':
main()
According to the above Perl and Python code, the output of main() should be:
Scanning... Station is 1250 AM Scanning... Station is 1380 AM Switching to FM Scanning... Station is 81.3 FM Scanning... Station is 89.1 FM Scanning... Station is 103.9 FM Scanning... Station is 81.3 FM Switching to AM Scanning... Station is 1510 AM Scanning... Station is 1250 AM
In the Ruby example below, a radio can switch to two states AM and FM and has a scan button to switch to the next station.
class State
def scan
@pos += 1
@pos = 0 if @pos == @stations.size
puts "Scanning… Station is", @stations[@pos], @name
end
end
class AmState < State
attr_accessor :radio, :pos, :name
def initialize radio
@radio = radio
@stations = ["1250", "1380", "1510"]
@pos = 0
@name = "AM"
end
def toggle_amfm
puts "Switching to FM"
@radio.state = @radio.fmstate
end
end
class FmState < State
attr_accessor :radio, :pos, :name
def initialize radio
@radio = radio
@stations = ["81.3", "89.1", "103.9"]
@pos = 0
@name = "FM"
end
def toggle_amfm
puts "Switching to AM"
@radio.state = @radio.amstate
end
end
class Radio
attr_accessor :amstate, :fmstate, :state
def initialize
@amstate = AmState.new self
@fmstate = FmState.new self
@state = @amstate
end
def toggle_amfm
@state.toggle_amfm
end
def scan
@state.scan
end
end
# Test Radio
radio = Radio.new
radio.scan
radio.toggle_amfm # Toggle the state
radio.scan
The state interface and two implementations. The state's method has a reference to the context object and is able to change its state.
interface IState {
/**
* Writer method for the state name.
*/
public function write(StateContext $context, string $name): void;
}
use namespace HH\Lib\Str;
final class LowerCaseState implements IState {
public function write(StateContext $context, string $name): void {
print Str\lowercase($name) . "\n";
$context->setState(new MultipleUpperCaseState());
}
}
use namespace HH\Lib\Str;
final class MultipleUpperCaseState implements IState {
private int $count = 0;
public function write(StateContext $context, string $name): void {
print Str\uppercase($name) . "\n";
++$this->count;
if ($this->count > 1) {
$context->setState(new LowerCaseState());
}
}
}
The context class has a state variable that it instantiates in an initial state, in this case StateA
. In its method, it uses the corresponding methods of the state object.
final class StateContext {
public function __construct(
private IState $state = new LowerCaseState()
) {}
/**
* Set the current state.
* Normally only called by classes implementing the State interface.
*/
public function setState(IState $state): void {
$this->state = $state;
}
public function write(string $name): void {
$this->state->write($this, $name);
}
}
The test below shows also the usage:
require 'vendor/hh_autoload.hh';
<<__EntryPoint>>
async function main(): Awaitable<void> {
$context = new StateContext();
$context->write('Monday');
$context->write('Tuesday');
$context->write('Wednesday');
$context->write('Thursday');
$context->write('Friday');
$context->write('Saturday');
$context->write('Sunday');
}
According to the above code, the output of main() entry point should be:
monday TUESDAY WEDNESDAY thursday FRIDAY SATURDAY sunday
References
- ↑ "Proxy - JavaScript | MDN". developer.mozilla.org. Retrieved 21 January 2022.
- ↑ revised from http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/
Strategy
[edit | edit source]
Scope
Object
Purpose
Behavioral
Intent
Define a family of algorithms, encapsulate each one, and make them interchangeable to let clients and algorithms vary independently from the clients using it.
Applicability
- when an object should be configurable with one of several algorithms,
- and all algorithms can be encapsulated,
- and one interface covers all encapsulations
Structure
Consequences
- + greater flexibility, reuse
- + can change algorithms dynamically
- - strategy creation & communication overhead
- - inflexible Strategy interface
Implementation
- exchanging information between a Strategy and its context
- static strategy selection via templates
Related patterns
- State, can activate several states, whereas a strategy can only activate one of the algorithms.
- Flyweight, provides a shared object that can be used in multiple contexts simultaneously, whereas a strategy focuses on one context.
- Decorator, changes the skin of an object, whereas a strategy changes the guts of an object.
- Composite, is used in combination with a strategy to improve efficiency.
Description
Suppose that you work for a company that builds a strategy game. Let's assume that you've come up with the following hierarchy of classes. All characters are able to walk, and there is also a method to render them on screen. The superclass takes care of the implementation of walk()
method, while each subclass provides its own implementation of display()
since each character looks different.
A new requirement arrives that the characters need to fight, too. Simple job you say; just add a fight()
method to Character
superclass. But, wait a moment; what about Workers? They cannot fight!
Well, one could think that you could simply override fight()
method in Worker
subclass to just do nothing.
class Worker {
....
void fight() {
// do nothing
}
....
}
But what if in the future there is a need for a Guard
class that can fight but shouldn’t walk? We need a cleaner solution. What about taking out the fight and walk behaviors from the superclass to an interface? That way, only the characters that are supposed to walk should implement the Walkable interface and only those characters that are supposed to fight should implement the Fightable
interface.
Well, this is another way to say for duplicate code. What if you need to make a small change to the fight behavior? You would need to modify all the classes. At this point we should put down three design principles to follow in our application development:
- Identify the aspects of your application that vary and separate them from what stays the same. Take what varies and “encapsulate” it so it won’t affect the rest of your code.
- Program to an interface not to an implementation.
- Favour composition over inheritance.
So, let's apply the 1st design principle. Pull out fight and walk behavior to different classes. And to apply the 2nd design principle as well, we have to pull out these behaviors to interfaces. Hence, we create a new WeaponBehavior interface to deal with fight behavior, and similarly a WalkBehavior interface to deal with walk behavior.
Character
s’ behaviors live in separate classes that implement a particular behavior interface. That way, the Character
classes don’t need to know any of the implementation details for their own behaviors. In addition, we no more rely on an implementation but on an interface. Other types of objects can use these behaviors, too, because they're not hidden inside our Character
class. And we can add new behaviors without modifying any of the existing ones or touching our character classes. So now, all we have to do is have our Character
class delegate all behavior information to the two behavior interfaces (so here comes the 3rd design principle). We do that by adding two instance variables to Character
, weapon
and walk
.
public abstract class Character {
private WeaponBehavior weapon;
private WalkBehavior walk;
public void fight() {
weapon.useWeapon(); // delegation of fight behavior
}
public void setWeapon(WeaponBehavior w) {
weapon = w;
}
...
abstract void display();
}
Each character object will set these variables polymorphically to reference the specific behavior type it would like at runtime.
public class Knight extends Character {
public Knight() {
weapon = new SwordBehavior();
walk = new GallopBehavior();
}
public void display() {
...
}
}
Think of these behaviors as families of algorithms. So, composition gives you a lot of flexibility. Not only does it let you encapsulate a family of algorithms into their own set of classes, but it also lets you change behavior at runtime as long as the object you are composing with, implements the correct behavior interface.
Examples
Cost
Think twice before implementing this pattern. You have to be sure your need is to frequently change an algorithm. You have to clearly anticipate the future, otherwise, this pattern will be more expensive than a basic implementation.
Creation
This pattern is expensive to create.
Maintenance
This pattern can be expensive to maintain. If the representation of a class often changes, you will have lots of refactoring.
Removal
This pattern is hard to remove too.
Advises
- Use the strategy term to indicate the use of the pattern to the other developers.
Implementations
The strategy pattern in ActionScript 3:
//invoked from application.initialize
private function init() : void
{
var context:Context;
context = new Context( new ConcreteStrategyA() );
context.execute();
context = new Context( new ConcreteStrategyB() );
context.execute();
context = new Context( new ConcreteStrategyC() );
context.execute();
}
package org.wikipedia.patterns.strategy
{
public interface IStrategy
{
function execute() : void ;
}
}
package org.wikipedia.patterns.strategy
{
public final class ConcreteStrategyA implements IStrategy
{
public function execute():void
{
trace( "ConcreteStrategyA.execute(); invoked" );
}
}
}
package org.wikipedia.patterns.strategy
{
public final class ConcreteStrategyB implements IStrategy
{
public function execute():void
{
trace( "ConcreteStrategyB.execute(); invoked" );
}
}
}
package org.wikipedia.patterns.strategy
{
public final class ConcreteStrategyC implements IStrategy
{
public function execute():void
{
trace( "ConcreteStrategyC.execute(); invoked" );
}
}
}
package org.wikipedia.patterns.strategy
{
public class Context
{
private var strategy:IStrategy;
public function Context(strategy:IStrategy)
{
this.strategy = strategy;
}
public function execute() : void
{
strategy.execute();
}
}
}
A struct in C can be used to define a class, and the strategy can be set using a function pointer. The following mirrors the Python example, and uses C99 features:
#include <stdio.h>
void print_sum(int n, int *array) {
int total = 0;
for (int i = 0; i < n; i++)
total += array[i];
printf("%d", total);
}
void print_array(int n, int *array) {
for (int i = 0; i < n; i++)
printf("%d ", array[i]);
}
typedef struct {
void (*submit_func)(int n, int *array); // function pointer
char *label; // instance label
} Button;
int main(void) {
// Create two instances with different strategies
Button button1 = { print_sum, "Add 'em" };
Button button2 = { print_array, "List 'em" };
int n = 10;
int numbers[n];
for (int i = 0; i < n; i++)
numbers[i] = i;
button1.submit_func(n, numbers);
button2.submit_func(n, numbers);
return 0;
}
The strategy pattern in C++ is similar to Java, but does not require dynamic allocation of objects.
#include <iostream>
class Strategy
{
public:
virtual int execute (int a, int b) = 0; // execute() is a so-called pure virtual function
// as a consequence, Strategy is a so-called abstract class
};
class ConcreteStrategyAdd:public Strategy
{
public:
int execute(int a, int b)
{
std::cout << "Called ConcreteStrategyAdd's execute()\n";
return a + b;
}
};
class ConcreteStrategySubstract:public Strategy
{
public:
int execute(int a, int b)
{
std::cout << "Called ConcreteStrategySubstract's execute()\n";
return a - b;
}
};
class ConcreteStrategyMultiply:public Strategy
{
public:
int execute(int a, int b)
{
std::cout << "Called ConcreteStrategyMultiply's execute()\n";
return a * b;
}
};
class Context
{
private:
Strategy* pStrategy;
public:
Context (Strategy& strategy)
: pStrategy(&strategy)
{
}
void SetStrategy(Strategy& strategy)
{
pStrategy = &strategy;
}
int executeStrategy(int a, int b)
{
return pStrategy->execute(a,b);
}
};
int main()
{
ConcreteStrategyAdd concreteStrategyAdd;
ConcreteStrategySubstract concreteStrategySubstract;
ConcreteStrategyMultiply concreteStrategyMultiply;
Context context(concreteStrategyAdd);
int resultA = context.executeStrategy(3,4);
context.SetStrategy(concreteStrategySubstract);
int resultB = context.executeStrategy(3,4);
context.SetStrategy(concreteStrategyMultiply);
int resultC = context.executeStrategy(3,4);
std::cout << "resultA: " << resultA << "\tresultB: " << resultB << "\tresultC: " << resultC << "\n";
}
public class StrategyPatternWiki
{
public static void Main(String[] args)
{
// Prepare strategies
var normalStrategy = new NormalStrategy();
var happyHourStrategy = new HappyHourStrategy();
var firstCustomer = new CustomerBill(normalStrategy);
// Normal billing
firstCustomer.Add(1.0, 1);
// Start Happy Hour
firstCustomer.Strategy = happyHourStrategy;
firstCustomer.Add(1.0, 2);
// New Customer
var secondCustomer = new CustomerBill(happyHourStrategy);
secondCustomer.Add(0.8, 1);
// The Customer pays
firstCustomer.Print();
// End Happy Hour
secondCustomer.Strategy = normalStrategy;
secondCustomer.Add(1.3, 2);
secondCustomer.Add(2.5, 1);
secondCustomer.Print();
}
}
// CustomerBill as class name since it narrowly pertains to a customer's bill
class CustomerBill
{
private IList<double> drinks;
// Get/Set Strategy
public IBillingStrategy Strategy { get; set; }
public CustomerBill(IBillingStrategy strategy)
{
this.drinks = new List<double>();
this.Strategy = strategy;
}
public void Add(double price, int quantity)
{
this.drinks.Add(this.Strategy.GetActPrice(price) * quantity);
}
// Payment of bill
public void Print()
{
double sum = 0;
foreach (var drinkCost in this.drinks)
{
sum += drinkCost;
}
Console.WriteLine($"Total due: {sum}.");
this.drinks.Clear();
}
}
interface IBillingStrategy
{
double GetActPrice(double rawPrice);
}
// Normal billing strategy (unchanged price)
class NormalStrategy : IBillingStrategy
{
public double GetActPrice(double rawPrice) => rawPrice;
}
// Strategy for Happy hour (50% discount)
class HappyHourStrategy : IBillingStrategy
{
public double GetActPrice(double rawPrice) => rawPrice * 0.5;
}
Another Example:
Delegates in C# follow the strategy pattern, where the delegate definition defines the strategy interface and the delegate instance represents the concrete strategy. .NET 3.5 defines the Func<,> delegate which can be used to quickly implement the strategy pattern as shown in the example below. Note the 3 different methods for defining a delegate instance.
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
var context = new Context<int>();
// Delegate
Func<int, int, int> concreteStrategy1 = PerformLogicalBitwiseOr;
// Anonymous Delegate
Func<int, int, int> concreteStrategy2 = delegate(int op1, int op2) { return op1 & op2; };
// Lambda Expressions
Func<int, int, int> concreteStrategy3 = (op1, op2) => op1 >> op2;
Func<int, int, int> concreteStrategy4 = (op1, op2) => op1 << op2;
context.Strategy = concreteStrategy1;
var result1 = context.Execute(8, 9);
context.Strategy = concreteStrategy2;
var result2 = context.Execute(8, 9);
context.Strategy = concreteStrategy3;
var result3 = context.Execute(8, 1);
context.Strategy = concreteStrategy4;
var result4 = context.Execute(8, 1);
}
static int PerformLogicalBitwiseOr(int op1, int op2)
{
return op1 | op2;
}
class Context<T>
{
public Func<T, T, T> Strategy { get; set; }
public T Execute(T operand1, T operand2)
{
return this.Strategy != null
? this.Strategy(operand1, operand2)
: default(T);
}
}
}
Using interfaces
using System;
namespace Wikipedia.Patterns.Strategy
{
// The strategy we will implement will be
// to advise on investments.
interface IHasInvestmentStrategy
{
long CalculateInvestment();
}
// Here we have one way to go about it.
class FollowTheMoon : IHasInvestmentStrategy
{
protected virtual int MoonPhase { get; set; }
protected virtual int AstrologicalSign { get; set; }
public FollowTheMoon(int moonPhase, int yourSign)
{
MoonPhase = moonPhase;
AstrologicalSign = yourSign;
}
public long CalculateInvestment()
{
if (MoonPhase == AstrologicalSign)
return 1000;
else
return 100 * (MoonPhase % DateTime.Today.Day);
}
}
// And here we have another.
// Note that each strategy may have its own dependencies.
// The EverythingYouOwn strategy needs a bank account.
class EverythingYouOwn : IHasInvestmentStrategy
{
protected virtual OtherLib.IBankAccessor Accounts { get; set; }
public EverythingYouOwn(OtherLib.IBankAccessor accounts)
{
Accounts = accounts;
}
public long CalculateInvestment()
{
return Accounts.GetAccountBalancesTotal();
}
}
// The InvestmentManager is where we want to be able to
// change strategies. This is the Context.
class InvestmentManager
{
public IHasInvestmentStrategy Strategy { get; set; }
public InvestmentManager(IHasInvestmentStrategy strategy)
{
Strategy = strategy;
}
public void Report()
{
// Our investment is determined by the current strategy.
var investment = Strategy.CalculateInvestment();
Console.WriteLine("You should invest {0} dollars!",
investment);
}
}
class Program
{
static void Main()
{
// Define some of the strategies we will use.
var strategyA = new FollowTheMoon( 8, 8 );
var strategyB = new EverythingYouOwn(
OtherLib.BankAccountManager.MyAccount);
// Our investment manager
var manager = new InvestmentManager(strategyA);
manager.Report();
// You should invest 1000 dollars!
manager.Strategy = strategyB;
manager.Report();
// You should invest 13521500000000 dollars!
}
}
}
An example in Common Lisp: Using strategy classes:
(defclass context ()
((strategy :initarg :strategy :accessor strategy)))
(defmethod execute ((c context))
(execute (slot-value c 'strategy)))
(defclass strategy-a () ())
(defmethod execute ((s strategy-a))
(print "Doing the task the normal way"))
(defclass strategy-b () ())
(defmethod execute ((s strategy-b))
(print "Doing the task alternatively"))
(execute (make-instance 'context
:strategy (make-instance 'strategy-a)))
In Common Lisp using first class functions:
(defclass context ()
((strategy :initarg :strategy :accessor strategy)))
(defmethod execute ((c context))
(funcall (slot-value c 'strategy)))
(let ((a (make-instance 'context
:strategy (lambda ()
(print "Doing the task the normal way")))))
(execute a))
(let ((b (make-instance 'context
:strategy (lambda ()
(print "Doing the task alternatively")))))
(execute b))
Similar to Python and Scala, Falcon supports first-class functions. The following implements the basic functionality seen in the Python example.
/*#
@brief A very basic button widget
*/
class Button( label, submit_func )
label = label
on_submit = submit_func
end
// Create two instances with different strategies ...
// ... and different ways to express inline functions
button1 = Button( "Add 'em",
function(nums)
n = 0
for val in nums: n+= val
return n
end )
button2 = Button( "Join 'em", { nums => " ".merge( [].comp(nums) ) } )
// Test each button
numbers = [1: 10]
printl(button1.on_submit(numbers)) // displays "45"
printl(button2.on_submit(numbers)) // displays "1 2 3 4 5 6 7 8 9"
Fortran 2003 adds procedure pointers, abstract interfaces and also first-class functions. The following mirrors the Python example.
module m_strategy_pattern
implicit none
abstract interface
!! A generic interface to a subroutine accepting array of integers
subroutine generic_function(numbers)
integer, dimension(:), intent(in) :: numbers
end subroutine
end interface
type :: Button
character(len=20) :: label
procedure(generic_function), pointer, nopass :: on_submit
contains
procedure :: init
end type Button
contains
subroutine init(self, func, label)
class(Button), intent(inout) :: self
procedure(generic_function) :: func
character(len=*) :: label
self%on_submit => func !! Procedure pointer
self%label = label
end subroutine init
subroutine summation(array)
integer, dimension(:), intent(in) :: array
integer :: total
total = sum(array)
write(*,*) total
end subroutine summation
subroutine join(array)
integer, dimension(:), intent(in) :: array
write(*,*) array !! Just write out the whole array
end subroutine join
end module m_strategy_pattern
!! The following program demonstrates the usage of the module
program test_strategy
use m_strategy_pattern
implicit none
type(Button) :: button1, button2
integer :: i
call button1%init(summation, "Add them")
call button2%init(join, "Join them")
call button1%on_submit([(i, i=1,10)]) !! Displays 55
call button2%on_submit([(i, i=1,10)]) !! Prints out the array
end program test_strategy
This Groovy example is a basic port of the Ruby using blocks example. In place of Ruby's blocks, the example uses Groovy's closure support.
class Context {
def strategy
Context(strategy) {
this.strategy = strategy
}
def execute() {
strategy()
}
}
def a = new Context({ println 'Style A' })
a.execute() // => Style A
def b = new Context({ println 'Style B' })
b.execute() // => Style B
def c = new Context({ println 'Style C' })
c.execute() // => Style C
An example in Java:
/** The classes that implement a concrete strategy should implement this.
* The Context class uses this to call the concrete strategy. */
interface Strategy {
int execute(int a, int b);
}
/** Implements the algorithm using the strategy interface */
class Add implements Strategy {
public int execute(int a, int b) {
System.out.println("Called Add's execute()");
return a + b; // Do an addition with a and b
}
}
class Subtract implements Strategy {
public int execute(int a, int b) {
System.out.println("Called Subtract's execute()");
return a - b; // Do a subtraction with a and b
}
}
class Multiply implements Strategy {
public int execute(int a, int b) {
System.out.println("Called Multiply's execute()");
return a * b; // Do a multiplication with a and b
}
}
/** Configured with a ConcreteStrategy object and maintains a reference to a Strategy object */
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int a, int b) {
return this.strategy.execute(a, b);
}
}
/** Tests the pattern */
class StrategyExample {
public static void main(String[] args) {
Context context;
// Three contexts following different strategies
context = new Context(new Add());
int resultA = context.executeStrategy(3, 4);
context = new Context(new Subtract());
int resultB = context.executeStrategy(3, 4);
context = new Context(new Multiply());
int resultC = context.executeStrategy(3, 4);
System.out.println("Result A: " + resultA );
System.out.println("Result B: " + resultB );
System.out.println("Result C: " + resultC );
}
}
An example in Java:
/** Imports a type of lambdas taking two arguments of the same type T and returning one argument of same type T */
import java.util.function.BinaryOperator;
/** Implements and assigns to variables the lambdas to be used later in configuring Context.
* FunctionalUtils is just a convenience class, as the code of a lambda
* might be passed directly to Context constructor, as for ResultD below, in main().
*/
class FunctionalUtils {
static final BinaryOperator<Integer> add = (final Integer a, final Integer b) -> {
System.out.println("Called add's apply().");
return a + b;
};
static final BinaryOperator<Integer> subtract = (final Integer a, final Integer b) -> {
System.out.println("Called subtract's apply().");
return a - b;
};
static final BinaryOperator<Integer> multiply = (final Integer a, final Integer b) -> {
System.out.println("Called multiply's apply().");
return a * b;
};
}
/** Configured with a lambda and maintains a reference to a lambda */
class Context {
/** a variable referencing a lambda taking two Integer arguments and returning an Integer: */
private final BinaryOperator<Integer> strategy;
public Context(final BinaryOperator<Integer> lambda) {
strategy = lambda;
}
public int executeStrategy(final int a, final int b) {
return strategy.apply(a, b);
}
}
/** Tests the pattern */
public class StrategyExample {
public static void main(String[] args) {
Context context;
context = new Context(FunctionalUtils.add);
final int resultA = context.executeStrategy(3,4);
context = new Context(FunctionalUtils.subtract);
final int resultB = context.executeStrategy(3, 4);
context = new Context(FunctionalUtils.multiply);
final int resultC = context.executeStrategy(3, 4);
context = new Context((final Integer a, final Integer b) -> a * b + 1);
final int resultD = context.executeStrategy(3,4);
System.out.println("Result A: " + resultA );
System.out.println("Result B: " + resultB );
System.out.println("Result C: " + resultC );
System.out.println("Result D: " + resultD );
}
}
Similar to Python and Scala, JavaScript supports first-class functions. The following implements the basic functionality seen in the Python example.
var Button = function(submit_func, label) {
this.label = label;
this.on_submit = submit_func;
};
var numbers = [1,2,3,4,5,6,7,8,9];
var sum = function(n) {
var sum = 0;
for ( var a in n ) {
sum = sum + n[a];
}
return sum;
};
var a = new Button(sum, "Add numbers");
var b = new Button(function(numbers) {
return numbers.join(',');
}, "Print numbers");
a.on_submit(numbers);
b.on_submit(numbers);
Perl has first-class functions, so as with Python, JavaScript and Scala, this pattern can be implemented without defining explicit subclasses and interfaces:
sort { lc($a) cmp lc($b) } @items
The strategy pattern can be formally implemented with Moose:
package Strategy;
use Moose::Role;
requires 'execute';
package FirstStrategy;
use Moose;
with 'Strategy';
sub execute {
print "Called FirstStrategy->execute()\n";
}
package SecondStrategy;
use Moose;
with 'Strategy';
sub execute {
print "Called SecondStrategy->execute()\n";
}
package ThirdStrategy;
use Moose;
with 'Strategy';
sub execute {
print "Called ThirdStrategy->execute()\n";
}
package Context;
use Moose;
has 'strategy' => (
is => 'rw',
does => 'Strategy',
handles => [ 'execute' ], # automatic delegation
);
package StrategyExample;
use Moose;
# Moose's constructor
sub BUILD {
my $context;
$context = Context->new(strategy => 'FirstStrategy');
$context->execute;
$context = Context->new(strategy => 'SecondStrategy');
$context->execute;
$context = Context->new(strategy => 'ThirdStrategy');
$context->execute;
}
package main;
StrategyExample->new;
The strategy pattern in PHP:
<?php
interface IStrategy {
public function execute();
}
class Context {
private $strategy;
public function __construct(IStrategy $strategy) {
$this->strategy = $strategy;
}
public function execute() {
$this->strategy->execute();
}
}
class ConcreteStrategyA implements IStrategy {
public function execute() {
echo "Called ConcreteStrategyA execute method\n";
}
}
class ConcreteStrategyB implements IStrategy {
public function execute() {
echo "Called ConcreteStrategyB execute method\n";
}
}
class ConcreteStrategyC implements IStrategy {
public function execute() {
echo "Called ConcreteStrategyC execute method\n";
}
}
class StrategyExample {
public function __construct() {
$context = new Context(new ConcreteStrategyA());
$context->execute();
$context = new Context(new ConcreteStrategyB());
$context->execute();
$context = new Context(new ConcreteStrategyC());
$context->execute();
}
}
new StrategyExample();
?>
PowerShell has first-class functions called ScriptBlocks, so the pattern can be modeled like Python, passing the function directly to the context instead of defining a class.
Function Context ([scriptblock]$script:strategy){
New-Module -Name Context -AsCustomObject {
Function Execute { & $strategy }
}
}
$a = Context {'Style A'}
$a.Execute()
(Context {'Style B'}).Execute()
$c = Context {'Style C'}
$c.Execute()
An alternative to using New-Module
Function Context ([scriptblock]$strategy){
{ & $strategy }.GetNewClosure()
}
$a = Context {'Style A'}
$a.Invoke()
& (Context {'Style B'})
$c = Context {'Style C'}
& $c
The following example is equivalent to the C# example 1 above, but in Python.
import abc
class Bill:
def __init__(self, billing_strategy: "BillingStrategy"):
self.drinks: list[float] = []
self.billing_strategy = billing_strategy
def add(self, price: float, quantity: int) -> None:
self.drinks.append(self.billing_strategy.get_act_price(price * quantity))
def __str__(self) -> str:
return f"£{sum(self.drinks)}"
class BillingStrategy(abc.ABC):
@abc.abstractmethod
def get_act_price(self, raw_price: float) -> float:
raise NotImplementedError
class NormalStrategy(BillingStrategy):
def get_act_price(self, raw_price: float) -> float:
return raw_price
class HappyHourStrategy(BillingStrategy):
def get_act_price(self, raw_price: float) -> float:
return raw_price * 0.5
def main() -> None:
normal_strategy = NormalStrategy()
happy_hour_strategy = HappyHourStrategy()
customer_1 = Bill(normal_strategy)
customer_2 = Bill(normal_strategy)
# Normal billing
customer_1.add(2.50, 3)
customer_1.add(2.50, 2)
# Start happy hour
customer_1.billing_strategy = happy_hour_strategy
customer_2.billing_strategy = happy_hour_strategy
customer_1.add(3.40, 6)
customer_2.add(3.10, 2)
# End happy hour
customer_1.billing_strategy = normal_strategy
customer_2.billing_strategy = normal_strategy
customer_1.add(3.10, 6)
customer_2.add(3.10, 2)
# Print the bills;
print(customer_1)
print(customer_2)
if __name__ == "__main__":
main()
Second example in Python:
class Strategy:
def execute(self, a, b):
pass
class Add(Strategy):
def execute(self, a, b):
return a + b
class Subtract(Strategy):
def execute(self, a, b):
return a - b
class Multiply(Strategy):
def execute(self, a, b):
return a * b
class Context:
def __init__(self, strategy):
self.strategy = strategy
def execute(self, a, b):
return self.strategy.execute(a, b)
if __name__ == "__main__":
context = None
context = Context(Add())
print "Add Strategy %d" % context.execute(10, 5)
context = Context(Subtract())
print "Subtract Strategy %d" % context.execute(10, 5)
context = Context(Multiply())
print "Multiply Strategy %d" % context.execute(10, 5)
Another example in Python: Python has first-class functions, so the pattern can be used simply by passing the function directly to the context instead of defining a class with a method containing the function. One loses information because the interface of the strategy is not made explicit, however, by simplifying the pattern in this manner.
Here's an example you might encounter in GUI programming, using a callback function:
class Button:
"""A very basic button widget."""
def __init__(self, submit_func, label):
self.on_submit = submit_func # Set the strategy function directly
self.label = label
# Create two instances with different strategies
button1 = Button(sum, "Add 'em")
button2 = Button(lambda nums: " ".join(map(str, nums)), "Join 'em")
# Test each button
numbers = range(1, 10) # A list of numbers 1 through 9
print button1.on_submit(numbers) # displays "45"
print button2.on_submit(numbers) # displays "1 2 3 4 5 6 7 8 9"
An example in Ruby:
class Context
def initialize(strategy)
extend(strategy)
end
end
module StrategyA
def execute
puts 'Doing the task the normal way'
end
end
module StrategyB
def execute
puts 'Doing the task alternatively'
end
end
module StrategyC
def execute
puts 'Doing the task even more alternatively'
end
end
a = Context.new(StrategyA)
a.execute #=> Doing the task the normal way
b = Context.new(StrategyB)
b.execute #=> Doing the task alternatively
a.execute #=> Doing the task the normal way
c = Context.new(StrategyC)
c.execute #=> Doing the task even more alternatively
Using blocks
The previous ruby example uses typical OO features, but the same effect can be accomplished with ruby's blocks in much less code.
class Context
def initialize(&strategy)
@strategy = strategy
end
def execute
@strategy.call
end
end
a = Context.new { puts 'Doing the task the normal way' }
a.execute #=> Doing the task the normal way
b = Context.new { puts 'Doing the task alternatively' }
b.execute #=> Doing the task alternatively
c = Context.new { puts 'Doing the task even more alternatively' }
c.execute #=> Doing the task even more alternatively
Like Python, Scala also supports first-class functions. The following implements the basic functionality shown in the Python example.
// A very basic button widget.
class Button[T](val label: String, val onSubmit: Range => T)
val button1 = new Button("Add", _ reduceLeft (_ + _))
val button2 = new Button("Join", _ mkString " ")
// Test each button
val numbers = 1 to 9 // A list of numbers 1 through 9
println(button1 onSubmit numbers) // displays 45
println(button2 onSubmit numbers) // displays 1 2 3 4 5 6 7 8 9
Template method
[edit | edit source]
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of algorithm without changing the algorithm's structure.
using System;
class MainApp
{
static void Main()
{
AbstractClass c;
c = new ConcreteClassA();
c.TemplateMethod();
c = new ConcreteClassB();
c.TemplateMethod();
// Wait for user
Console.Read();
}
}
// "AbstractClass"
abstract class AbstractClass
{
public abstract void PrimitiveOperation1();
public abstract void PrimitiveOperation2();
// The "Template method"
public void TemplateMethod()
{
PrimitiveOperation1();
PrimitiveOperation2();
Console.WriteLine("");
}
}
// "ConcreteClass"
class ConcreteClassA : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("ConcreteClassA.PrimitiveOperation1()");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("ConcreteClassA.PrimitiveOperation2()");
}
}
class ConcreteClassB : AbstractClass
{
public override void PrimitiveOperation1()
{
Console.WriteLine("ConcreteClassB.PrimitiveOperation1()");
}
public override void PrimitiveOperation2()
{
Console.WriteLine("ConcreteClassB.PrimitiveOperation2()");
}
}
/**
* An abstract class that is common to several games in
* which players play against the others, but only one is
* playing at a given time.
*/
abstract class Game {
protected int playersCount;
abstract void initializeGame();
abstract void makePlay(int player);
abstract boolean endOfGame();
abstract void printWinner();
/* A template method : */
public final void playOneGame(int playersCount) {
this.playersCount = playersCount;
initializeGame();
int j = 0;
while (!endOfGame()) {
makePlay(j);
j = (j + 1) % playersCount;
}
printWinner();
}
}
// Now we can extend this class in order
// to implement actual games:
class Monopoly extends Game {
/* Implementation of necessary concrete methods */
void initializeGame() {
// Initialize players
// Initialize money
}
void makePlay(int player) {
// Process one turn of player
}
boolean endOfGame() {
// Return true if game is over
// according to Monopoly rules
}
void printWinner() {
// Display who won
}
/* Specific declarations for the Monopoly game. */
// ...
}
import java.util.Random;
class SnakesAndLadders extends Game {
/* Implementation of necessary concrete methods */
void initializeGame() {
// Initialize players
playerPositions = new int[playersCount];
for (int i = 0; i < playersCount; i++) {
playerPositions[i] = 0;
}
die = new Random();
winnerId = -1;
}
void makePlay(int player) {
// Roll the die
int dieRoll = die.nextInt(6) + 1;
// Move the token
playerPositions[player] += dieRoll;
// Move up or down because of the ladders or the snakes
int penaltyOrBonus = board[playerPositions[player]];
playerPositions[player] += penaltyOrBonus;
if (playerPositions[player] > 8) {
// Has reached the top square
winnerId = player;
}
}
boolean endOfGame() {
// The game is over when a winner exists
return (winnerId != -1);
}
void printWinner() {
System.out.println("Player #" + winnerId + " has won!");
}
/* Specific declarations for the Snakes and Ladders game. */
// The board from the bottom square to the top square
// Each integer is a square
// Negative values are snake heads with their lengths
// Positive values are ladder bottoms with their heights
private static final int[] board = {0, 0, -1, 0, 3, 0, 0, 0, -5, 0};
// The player positions
// Each integer represents one player
// The integer is the position of the player (index) on the board
private int[] playerPositions = null;
private Random die = null;
private int winnerId = -1;
}
/**
* The same example from above but with Java 8
* functional interfaces. Note that now Game
* class doesn't have to be abstract.
*/
class Game {
protected int playersCount;
/*
* Note that abstract methods are now replaced
* with functional interface instances. It gives you a lot
* more of flexibility: you can require all of them to be set
* via constructor, you can wrap them or you can set default
* implementations.
*/
private final Runnable initializeGame;
private final Consumer<Integer> makePlay;
private final Supplier<Boolean> endOfGame;
private final Runnable printWinner;
/*
* Constructor with parameters initialization.
* Note that you can define multiple constructors
* with different sets of parameters or define
* default values for null values. Subclasses
* are required to call at least one of constructors
* if you don't define a default one.
*/
protected Game(Consumer<Integer> makePlay, Supplier<Boolean> endOfGame) {
// you can set default if omitted
this.makePlay = Optional.ofNullable(makePlay).orElseGet((i)->{});
// you can require non-null param
this.endOfGame = Objects.requireNonNull(endOfGame);
// ... and set defaults for optional parameters
this.initializeGame = ()->{};
this.printWinner = ()->{};
}
/*
* Provide setters for customization if you don't provide
* constructor for every combination of parameters.
*/
protected void setGameInitializer(Runnable initializeGame) {
this.initializeGame = Objects.requireNonNull(initializeGame);
}
protected void setWinnerPrinter(Runnable printWinner) {
this.printWinner = Objects.requireNonNull(printWinner);
}
/* A template method calling functional interfaces: */
public final void playOneGame(int playersCount) {
this.playersCount = playersCount;
initializeGame.run();
int j = 0;
while (!endOfGame.get()) {
makePlay.accept(j);
j = (j + 1) % playersCount;
}
printWinner.run();
}
}
// Now we can extend this class in order
// to implement an actual game.
// Note that there's no need to define methods
// that you don't want to override. For methods
// you'd like to override you can either supply
// a functional reference or a lambda:
class Monopoly extends Game {
public Monopoly() {
//Initialize parent with functional references
super(this::makePlay, this::endOfGame);
// make additional tweaking if you need to.
// you can even change it in runtime if you want!
setGameInitializer(this::startGame);
}
/*
* Implementation of concrete method. Note that names
* can be different now!
*/
void startGame() {
// Initialize players
// Initialize money
}
void makePlay(int player) {
// Process one turn of player
}
boolean endOfGame() {
// Return true if game is over
// according to Monopoly rules
}
/* Specific declarations for the Monopoly game. */
// ...
}
abstract class Game
{
abstract protected void initialize();
abstract protected void startPlay();
abstract protected void endPlay();
/** Template method */
public final void play()
{
/** Primitive */
initialize();
/** Primitive */
startPlay();
/** Primitive */
endPlay();
}
}
class Mario extends Game
{
protected void initialize()
{
echo "Mario Game Initialized! Start playing.", PHP_EOL;
}
protected void startPlay()
{
echo "Mario Game Started. Enjoy the game!", PHP_EOL;
}
protected void endPlay()
{
echo "Mario Game Finished!", PHP_EOL;
}
}
class Tankfight extends Game
{
protected void initialize()
{
echo "Tankfight Game Initialized! Start playing.", PHP_EOL;
}
protected void startPlay()
{
echo "Tankfight Game Started. Enjoy the game!", PHP_EOL;
}
protected void endPlay()
{
echo "Tankfight Game Finished!", PHP_EOL;
}
}
$game = new Tankfight();
$game->play();
$game = new Mario();
$game->play();
case class Song(name: String, lyrics: String, music: String)
trait ConcertPlayer {
def specialEffectsStart()
def greetTheAudience()
def introduceYourSelf()
def songsIterator(): Iterable[Song]
def sayGoodbye()
final def playConcert() {
specialEffectsStart()
greetTheAudience()
introduceYourSelf()
songsIterator() foreach { song =>
println(s"Now we will play the song named ${song.name}")
println(song.music)
println(song.lyrics)
}
sayGoodbye()
}
}
class Artist1 extends ConcertPlayer {
def sayGoodbye() {
println("See you!")
}
def songsIterator(): Iterable[Song] =
1 to 10 map { index =>
Song(s"song $index", s"lyrics $index", s"music $index")
}
def introduceYourSelf() {
println("I'm the Artist1!")
}
def greetTheAudience() {
println("Hey!")
}
def specialEffectsStart() {
println("Pyrotechnics...")
}
}
class Artist2 extends ConcertPlayer {
def sayGoodbye() {
println("Bye-Bye")
}
def songsIterator(): Iterable[Song] =
11 to 21 map { index =>
Song(s"song $index", s"lyrics $index", s"music $index")
}
def introduceYourSelf() {
println("I'm the Artist2!")
}
def greetTheAudience() {
println("Hi!")
}
def specialEffectsStart() {
println("Flames...")
}
}
object TemplateMethodTest extends App {
val artist1 = new Artist1
val artist2 = new Artist2
artist1.playConcert()
artist2.playConcert()
}
Visitor
[edit | edit source]
The visitor pattern allows you to easily perform a given operation (function, algorithm, etc…) on each element of a complex structure. The benefit is that you can easily add other operations to perform and you can easily change the structure of the elements. The principle is that the classes that are used to perform the operations and the classes that scroll the structures are different. It also means that, if you know that you will always have only one operation to perform on the structure, this pattern is useless.
Let's take the simple data class:
Element |
We want to perform an operation on it. Instead of implementing it inside of the class, we will use a visitor class. A visitor class is a class that performs an action on an object. It will perform an action on a whole structure by being called for each element. However, for now, we only have one object. The visitor will be called by the visit method by the data object, and the object will be called by the accept method by the client:
|
| |||||||
|
| |||||||
|
Then you can define a structure of data object and each object will call the accept() method on its sub-elements. You may think that the main drawback of this pattern is that even if the visitor can process all the elements, it does not process it as a whole, i.e. it can't connect the different elements together, so the pattern is limited. Not at all. The visitor can keep information about the elements it has already visited (for example to log lines with appropriate indentation). If the visitor needs information from all the elements (for example to compute a percentage based on the sum), it can visit all the elements, store information, and actually process all the information after the last visit using another method. In other words, you can add states to your visitor.
This process is essentially equivalent to getting the collection's iterator, and using a while(iterator.hasNext()) loop to invoke visitor.visit(iterator.next()). The key difference is that the collection can decide exactly how to step through the elements. If you're familiar with iterators, you may be thinking that the iterator can decide how to step through, too, and the iterator is usually defined by the collection, so what's the difference? The difference is that the iterator is still bound to a while loop, visiting each element in succession, one at a time. With the visitor pattern, the collection could conceivably create a separate thread for each element and have the visitor visiting them concurrently. That's just one example of ways that the collection may decide to vary the method of visitation in a manner that can't be mimicked by an iterator. The point is, it's encapsulated, and the collection can implement the pattern in whatever way it feels is best. More importantly, it can change the implementation at any time, without affecting client code, because the implementation is encapsulated in the foreach method.
An example implementation of Visitor Pattern: String
To illustrate the visitor pattern, let's imagine we're reinventing Java's String class (it'll be a pretty ridiculous reinvention, but it'll be good for this exercise). We're not going to implement very much of the class, but let's assume that we're storing a set of chars that make up the string, and we have a method called getCharAt that takes an int as its only argument, and returns the character at that position in the string, as a char. We also have a method called length that takes no arguments, and returns an int that gives the number of characters in the string. Let's also assume that we want to provide an implementation of the visitor pattern for this class that will take an instance that implements the ICharacterVisitor interface (that we'll define, below), and calls its visit method for each character in the string. First we need to define what this ICharacterVisitor interface looks like:
public interface ICharacterVisitor {
public void visit(final char aChar);
}
Easy enough. Now, let's get down to our class, which we'll call MyString, and it looks something like this:
public class MyString {
// … other methods, fields
// Our main implementation of the visitor pattern
public void foreach(final ICharacterVisitor aVisitor) {
int length = this.length();
// Loop over all the characters in the string
for (int i = 0; i < length; i++) {
// Get the current character, and let the visitor visit it.
aVisitor.visit(this.getCharAt(i));
}
}
// … other methods, fields
}// end class MyString
So, that was pretty painless. What can we do with this? Well, let's make a class called MyStringPrinter, which prints an instance of MyString to the standard output.
public class MyStringPrinter implements ICharacterVisitor {
// We have to implement this method because we're implementing the ICharacterVisitor
// interface
public void visit(final char aChar) {
// All we're going to do is print the current character to the standard output
System.out.print(aChar);
}
// This is the method you call when you want to print a string
public void print(final MyString aStr) {
// we'll let the string determine how to get each character, and
// we already defined what to do with each character in our
// visit method.
aStr.foreach(this);
}
} // end class MyStringPrinter
That was simple too. Of course, it could've been a lot simpler, right? We didn't need the foreach method in MyString, and we didn't need MyStringPrinter to implement the visitor, we could have just used the MyString classes getCharAt and length methods to set up our own for loop ourselves and printed each char inside the loop. Well, sure you could, but what if MyString isn't MyString but instead is MyBoxOfRocks.
Another example implementation of Visitor Pattern: Rock
In a box of rocks, is there a set order that the rocks are in? Unlikely. Of course MyBoxOfRocks has to store the rocks somehow. Maybe, it stores them in an array, and there is actually a set order of the rocks, even if it is artificially introduced for the sake of storage. On the other hand, maybe it doesn't. The point is once again that it is an implementation detail that you as the client of MyBoxOfRocks shouldn't have to worry about, and should never rely on.
Presumably, MyBoxOfRocks wants to provide someway for clients to get to the rocks inside it. It could, once again, introduce an artificial order to the rocks; assign each rock an index and provide a method like public Rock getRock(int aRockNumber). Or maybe it wants to put names on all the rocks and let you access it like public Rock getRock(String aRockName). But maybe it's really just a box of rocks, and there are no names, no numbers, no way of identifying which rock you want; all you know is you want the rocks. Alright, let's try it with the visitor pattern. First, our visitor interface (assume Rock is already defined somewhere, we don't care what it is or what it does):
public interface IRockVisitor {
public void visit(final Rock aRock);
}
Easy. Now out MyBoxOfRocks
public class MyBoxOfRocks {
private Rock[] fRocks;
//… some kind of instantiation code
public void foreach(final IRockVisitor aVisitor) {
int length = fRocks.length;
for (int i = 0; i < length; i++) {
aVisitor.visit(fRocks[i]);
}
}
} // End class MyBoxOfRocks
Huh, what do you know, it does store them in an array. But what do we care now? We already wrote the visitor interface, and all we have to do now is implement it in some class that defines the actions to take for each rock, which we would have to do inside a for loop anyway. Besides, the array is private, our visitor doesn't have any access to that.
And what if the implementor of MyBoxOfRocks did a little homework and found out that comparing a number to zero is infinitesimally faster than comparing it to a non-zero value? Infinitesimal, sure, but maybe when you're iterating over 10 million rocks, it makes a difference (maybe!). So, he decides to change the implementation:
public void foreach(final IRockVisitor aVisitor) {
int length = fRocks.length;
for (int i = length - 1; i >= 0; i--) {
aVisitor.visit(fRocks[i]);
}
}
Now, he's iterating backwards through the array and saving a (very) little time. He's changed the implementation because he found a better way. You didn't have to worry about finding the best way, and you didn't have to change your code because the implementation is encapsulated. And that's not the half of it. Maybe, a new coder takes control of the project, and maybe this coder hates arrays and decides to totally change it:
public class MyBoxOfRocks {
// This coder really likes Linked Lists
private class RockNode {
Rock iRock;
RockNode iNext;
RockNode(final Rock aRock, final RockNode aNext) {
this.iRock = aRock;
this.iNext = aNext;
}
} // end inner class RockNode
private RockNode fFirstRock;
// … some instantiation code goes in here
// Our new implementation
public void foreach (final IRockVisitor aVisitor) {
RockNode current = this.fFirstRock;
// a null value indicates the list is ended
while (current != null) {
// have the visitor visit the current rock
aVisitor.visit(current.iRock);
// step to the next rock
current = current.iNext;
}
}
}
Now, maybe in this instance, linked lists were a poor idea, not as fast as a nice lean array and a for loop. On the other hand, you don't know what else this class is supposed to do. Maybe, providing access to the rocks is only a small part of what it does, and linked lists fit in better with the rest of the requirements. In case I haven't said it enough yet, the point is that you as the client of MyBoxOfRocks don't have to worry about changes to the implementation, the visitor pattern protects you from it.
I have one more trick up my sleeve. Maybe, the implementor of MyBoxOfRocks notices that a lot of visitors are taking a really long time to visit each rock, and it's taking far too long for the foreach method to return because it has to wait for all visitors to finish. He decides it can't wait that long, and he also decides that some of these operations can probably be going on all at once. So, he decides to do something about it, namely, this:
// Back to our backward-array model
public void foreach(final IRockVisitor aVisitor) {
Thread t; // This should speed up the return
int length = fRocks.length;
for (int i = length - 1; i >= 0; i--) {
final Rock current = fRocks[i];
t = new Thread() {
public void run() {
aVisitor.visit(current);
}
}; // End anonymous Thread class
t.start(); // Run the thread we just created.
}
}
If you're familiar with threads, you'll understand what's going on here. If you're not, I'll quickly summarize: a Thread is basically something that can run "simultaneously" with other threads on the same machine. They don't actually run simultaneously of course, unless maybe you have a multi-processor machine, but as far as Java is concerned, they do. So, for instance, when we created this new Thread called t, and defined what happens when the Thread is run (with the run method, naturally), we can then start the Thread, and it will start running, splitting cycles on the processor with other Threads, right away, doesn't have to wait for the current method to return. Likewise, we can start it running and then continue on our own way immediately, without waiting for it to return. So, with the above implementation, the only time we need to spend in this method is the time it takes to instantiate all the threads, start them running, and loop over the array; we don't have to wait for the visitor to actually visit each Rock before we can loop, we just loop right away, and the visitor does its thing on whatever CPU cycles it can swipe. The whole visiting process might take a long time – maybe even longer, if it looses some cycles because of the multiple threads, but the thread from which foreach was invoked doesn't have to wait for it to finish: it can return from the method and be on it's way much faster.
If you're confused about the use of the final Rock called "current" in the above code, it's just a bit of technicality using anonymous classes: they can't access non-final local variables. Even though fRocks doesn't fit into this category (it's not local, but an instance variable), i does. If you tried to remove this line and simply put fRocks[i] in the run method, it wouldn't compile.
So, what happens if you're the visitor, and you decide that you need to visit each rock one at a time? There's a number of reasons this might happen such as, if your visit method changes your instance variables, or it depends on the results of previous calls of visit. Well, the implementation inside the foreach method is encapsulated, so you don't know if it's using separate threads or not. Sure, you could figure it out with some fancy debugging, or some clever printing to std out, but wouldn't it be nice, if you didn't have to? And if you could be sure that, if they change it in the next version, your code will still work properly? Well, fortunately, Java provides the synchronize mechanism, which is basically an elaborate device for locking up blocks of code so that only one Thread can access them at a time. This won't conflict with the interests of the multi-threaded implementation either, because the locked-out thread still won't block the thread that created them, but they will just sit and wait patiently, only blocking code on itself. That's all well beyond the scope of this section, however, but be aware that it's available and probably worth looking into, if you're going to be using synchronicity-sensitive visitors.
Examples
Cost
This pattern is flexible enough not to block you. At worst, you will need to spend time thinking about how to solve problems, but this pattern will never block you.
Creation
This pattern is expensive to create, if your code already exists.
Maintenance
It is easy to adapt the code with this pattern, even if there are new links between the item visits.
Removal
This pattern can be removed using refactoring operations from your IDE.
Advises
- Use the visitor and visit term to indicate the use of the pattern to the other developers.
- If you have and will always have only one visitor, you'd rather implement the composite pattern.
Implementations
The following example is an example in the C# programming language:
using System;
namespace VisitorPattern
{
class Program
{
static void Main(string[] args)
{
var car = new Car();
CarElementVisitor doVisitor = new CarElementDoVisitor();
CarElementVisitor printVisitor = new CarElementPrintVisitor();
printVisitor.visit(car);
doVisitor.visit(car);
}
}
public interface CarElementVisitor
{
void visit(Body body);
void visit(Car car);
void visit(Engine engine);
void visit(Wheel wheel);
}
public interface CarElement
{
void accept(CarElementVisitor visitor); // CarElements have to provide accept().
}
public class Wheel : CarElement
{
public String name { get; set; }
public void accept(CarElementVisitor visitor)
{
visitor.visit(this);
}
}
public class Engine : CarElement
{
public void accept(CarElementVisitor visitor)
{
visitor.visit(this);
}
}
public class Body : CarElement
{
public void accept(CarElementVisitor visitor)
{
visitor.visit(this);
}
}
public class Car
{
public CarElement[] elements { get; private set; }
public Car()
{
elements = new CarElement[]
{ new Wheel{name = "front left"}, new Wheel{name = "front right"},
new Wheel{name = "back left"} , new Wheel{name="back right"},
new Body(), new Engine() };
}
}
public class CarElementPrintVisitor : CarElementVisitor
{
public void visit(Body body)
{
Console.WriteLine("Visiting body");
}
public void visit(Car car)
{
Console.WriteLine("\nVisiting car");
foreach (var element in car.elements)
{
element.accept(this);
}
Console.WriteLine("Visited car");
}
public void visit(Engine engine)
{
Console.WriteLine("Visiting engine");
}
public void visit(Wheel wheel)
{
Console.WriteLine("Visiting " + wheel.name + " wheel");
}
}
public class CarElementDoVisitor : CarElementVisitor
{
public void visit(Body body)
{
Console.WriteLine("Moving my body");
}
public void visit(Car car)
{
Console.WriteLine("\nStarting my car");
foreach (var element in car.elements)
{
element.accept(this);
}
}
public void visit(Engine engine)
{
Console.WriteLine("Starting my engine");
}
public void visit(Wheel wheel)
{
Console.WriteLine("Kicking my " + wheel.name);
}
}
}
The following example is in the D programming language:
import std.stdio;
import std.string;
interface CarElementVisitor {
void visit(Body bod);
void visit(Car car);
void visit(Engine engine);
void visit(Wheel wheel);
}
interface CarElement{
void accept(CarElementVisitor visitor);
}
class Wheel : CarElement {
private string name;
this(string name) {
this.name = name;
}
string getName() {
return name;
}
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Engine : CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Body : CarElement {
public void accept(CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Car {
CarElement[] elements;
public CarElement[] getElements() {
return elements;
}
public this() {
elements =
[
cast(CarElement) new Wheel("front left"),
cast(CarElement) new Wheel("front right"),
cast(CarElement) new Wheel("back left"),
cast(CarElement) new Wheel("back right"),
cast(CarElement) new Body(),
cast(CarElement) new Engine()
];
}
}
class CarElementPrintVisitor : CarElementVisitor {
public void visit(Wheel wheel) {
writefln("Visiting "~ wheel.getName() ~ " wheel");
}
public void visit(Car car) {
writefln("\nVisiting car");
foreach(CarElement element ; car.elements) {
element.accept(this);
}
writefln("Visited car");
}
public void visit(Engine engine) {
writefln("Visiting engine");
}
public void visit(Body bod) {
writefln("Visiting body");
}
}
class CarElementDoVisitor : CarElementVisitor {
public void visit(Body bod) {
writefln("Moving my body");
}
public void visit(Car car) {
writefln("\nStarting my car");
foreach(CarElement carElement ; car.getElements()) {
carElement.accept(this);
}
writefln("Started car");
}
public void visit(Engine engine) {
writefln("Starting my engine");
}
public void visit(Wheel wheel) {
writefln("Kicking my "~ wheel.name);
}
}
void main() {
Car car = new Car;
CarElementVisitor printVisitor = new CarElementPrintVisitor;
CarElementVisitor doVisitor = new CarElementDoVisitor;
printVisitor.visit(car);
doVisitor.visit(car);
}
The following example is in the Java programming language:
interface CarElementVisitor {
void visit(Body body);
void visit(Car car);
void visit(Engine engine);
void visit(Wheel wheel);
}
interface CarElement {
void accept(CarElementVisitor visitor); // CarElements have to provide accept().
}
class Wheel implements CarElement {
private String name;
public Wheel(final String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void accept(final CarElementVisitor visitor) {
/*
* accept(CarElementVisitor) in Wheel implements
* accept(CarElementVisitor) in CarElement, so the call
* to accept is bound at run time. This can be considered
* the first dispatch. However, the decision to call
* visit(Wheel) (as opposed to visit(Engine) etc.) can be
* made during compile time since 'this' is known at compile
* time to be a Wheel. Moreover, each implementation of
* CarElementVisitor implements the visit(Wheel), which is
* another decision that is made at run time. This can be
* considered the second dispatch.
*/
visitor.visit(this);
}
}
class Engine implements CarElement {
/**
* Accept the visitor.
* This method will call the method visit(Engine)
* and not visit(Wheel) nor visit(Body)
* because <tt>this</tt> is declared as Engine.
* That's why we need to define this code in each car element class.
*/
public void accept(final CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Body implements CarElement {
/**
* Accept the visitor.
* This method will call the method visit(Body)
* and not visit(Wheel) nor visit(Engine)
* because <tt>this</tt> is declared as Body.
* That's why we need to define this code in each car element class.
*/
public void accept(final CarElementVisitor visitor) {
visitor.visit(this);
}
}
class Car implements CarElement {
CarElement[] elements;
public Car() {
// Create new Array of elements
this.elements = new CarElement[] { new Wheel("front left"),
new Wheel("front right"), new Wheel("back left") ,
new Wheel("back right"), new Body(), new Engine() };
}
public void accept(final CarElementVisitor visitor) {
visitor.visit(this);
}
}
/**
* One visitor.
* You can define as many visitor as you want.
*/
class CarElementPrintVisitor implements CarElementVisitor {
public void visit(final Body body) {
System.out.println("Visiting body");
}
public void visit(final Car car) {
System.out.println("Visiting car");
for(CarElement element : elements) {
element.accept(visitor);
}
System.out.println("Visited car");
}
public void visit(final Engine engine) {
System.out.println("Visiting engine");
}
public void visit(final Wheel wheel) {
System.out.println("Visiting " + wheel.getName() + " wheel");
}
}
/**
* Another visitor.
* Each visitor has one functional purpose.
*/
class CarElementDoVisitor implements CarElementVisitor {
public void visit(final Body body) {
System.out.println("Moving my body");
}
public void visit(final Car car) {
System.out.println("Starting my car");
for(final CarElement element : elements) {
element.accept(visitor);
}
System.out.println("Started my car");
}
public void visit(final Engine engine) {
System.out.println("Starting my engine");
}
public void visit(final Wheel wheel) {
System.out.println("Kicking my " + wheel.getName() + " wheel");
}
}
public class VisitorDemo {
public static void main(final String[] arguments) {
final CarElement car = new Car();
car.accept(new CarElementPrintVisitor());
car.accept(new CarElementDoVisitor());
}
}
(defclass auto ()
((elements :initarg :elements)))
(defclass auto-part ()
((name :initarg :name :initform "<unnamed-car-part>")))
(defmethod print-object ((p auto-part) stream)
(print-object (slot-value p 'name) stream))
(defclass wheel (auto-part) ())
(defclass body (auto-part) ())
(defclass engine (auto-part) ())
(defgeneric traverse (function object other-object))
(defmethod traverse (function (a auto) other-object)
(with-slots (elements) a
(dolist (e elements)
(funcall function e other-object))))
;; do-something visitations
;; catch all
(defmethod do-something (object other-object)
(format t "don't know how ~s and ~s should interact~%" object other-object))
;; visitation involving wheel and integer
(defmethod do-something ((object wheel) (other-object integer))
(format t "kicking wheel ~s ~s times~%" object other-object))
;; visitation involving wheel and symbol
(defmethod do-something ((object wheel) (other-object symbol))
(format t "kicking wheel ~s symbolically using symbol ~s~%" object other-object))
(defmethod do-something ((object engine) (other-object integer))
(format t "starting engine ~s ~s times~%" object other-object))
(defmethod do-something ((object engine) (other-object symbol))
(format t "starting engine ~s symbolically using symbol ~s~%" object other-object))
(let ((a (make-instance 'auto
:elements `(,(make-instance 'wheel :name "front-left-wheel")
,(make-instance 'wheel :name "front-right-wheel")
,(make-instance 'wheel :name "rear-right-wheel")
,(make-instance 'wheel :name "rear-right-wheel")
,(make-instance 'body :name "body")
,(make-instance 'engine :name "engine")))))
;; traverse to print elements
;; stream *standard-output* plays the role of other-object here
(traverse #'print a *standard-output*)
(terpri) ;; print newline
;; traverse with arbitrary context from other object
(traverse #'do-something a 42)
;; traverse with arbitrary context from other object
(traverse #'do-something a 'abc))
The following example is an example in the Scala programming language:
trait Visitable {
def accept[T](visit: Visitor[T]): T = visit(this)
}
trait Visitor[T] {
def apply(visitable: Visitable): T
}
trait Node extends Visitable
trait Operand extends Node
case class IntegerLiteral(value: Long) extends Operand
case class PropertyReference(name: String) extends Operand
trait Operator extends Node
case object Greater extends Operator
case object Less extends Operator
case class ComparisonOperation(left: Operand, op: Operator, right: Operand) extends Node
class NoSqlStringifier extends Visitor[String] {
def apply(visitable: Visitable): String = visitable match {
case IntegerLiteral(value) => value.toString
case PropertyReference(name: String) => name
case Greater => s">"
case Less => "<"
case ComparisonOperation(left, operator, right) =>
s"${left.accept(this)}: { ${operator.accept(this)}: ${right.accept(this)} }"
}
}
class SqlStringifier extends Visitor[String] {
def apply(visitable: Visitable): String = visitable match {
case IntegerLiteral(value) => value.toString
case PropertyReference(name: String) => name
case Greater => ">"
case Less => "<"
case ComparisonOperation(left, operator, right) =>
s"WHERE ${ left.accept(this)} ${operator.accept(this)} ${right.accept(this) }"
}
}
object VisitorPatternTest {
def main(args: Array[String]) {
val condition: Node = ComparisonOperation(PropertyReference("price"), Greater, IntegerLiteral(12))
println(s"No sql representation = ${condition.accept(new NoSqlStringifier)}")
println(s"Sql representation = ${condition.accept(new SqlStringifier)}")
}
}
Output:
No sql representation = price: { >: 12 } Sql representation = WHERE price > 12