Anda di halaman 1dari 38

Design Patterns

Nitish Bhatia Software Engineer JK Technosoft

What is a Design Pattern?


A design pattern systematically names, motivates, and explains a general design that addresses a recurring design problem in object-oriented systems. It describes the problem, the solution, when to apply the solution, and its consequences. It also gives implementation hints and examples. The solution is a general arrangement of objects and classes that solve the problem. The solution is customized and implemented to solve the problem in a particular context.
(Gang of Four)

Why we require design patterns?


Software Changes

There are great tools at our disposal to ensure that system are designed to change rapidly while reducing negative impact these alterations can bring.
One such tool

DESIGN PATTERNS

The Pattern Catalog


Creational Class
Factory Method

Structural
Abstract Server Adapter

Behavioral
Template Method Interpreter

Object

Abstract Factory Expanding Monostate Monostate Prototype Singleton

Adapter Bridge Composite Decorator External Polymorphism Faade Proxy Null Object

Active Object Acyclic Visitor Command Iterator Observer State Strategy Visitor

Purpose
Creational: concerned with object creation Structural: concerned with composition of classes or objects Behavioral: concerned with ways classes or objects interact

Scope
Class: relationships between classes and derived classes; static Object: relationships between objects; dynamic

The Pattern Catalog

Purpose
Creational: concerned with object creation Structural: concerned with composition of classes or objects Behavioral: concerned with ways classes or objects interact

Scope
Class: relationships between classes and derived classes; static Object: relationships between objects; dynamic

Creational Patterns

Creational Patterns describe object-creation mechanisms that enable greater levels of reuse in evolving systems

Factory Design Pattern

Logical Model

Physical Model

Logical Model
It uses three types of primary actors

Client is an object that require instance of another object(the product)


Factory creates a new instance of the product, passing it back to the client

Client uses the factory to create an instance of the product.

Physical Model
Uses two abstract classes Factory Product

Client uses an instance of a concrete subclass of Factory(ConcreteFactory) to create an instance of a concrete Product subclass (ConcreteProduct)

Implementation of the Factory pattern


abstract class Computer { public abstract int Mhz { get; } }//Computer abstract class ComputerFactory { public abstract Computer GetComputer(); }//ComputerFactory

The ConcreteComputer and ConcreteComputerFactory classes found below extend these abstract class
class ConcreteComputer:Computer { int _mhz = 500; public override int Mhz { get { return _mhz; } }//Mhz }//ConcreteComputer class ConcreteComputerFactory:ComputerFactory { public override Computer GetComputer() { return new ConcreteComputer(); }//GetComputer }//ConcreteComputerFactory

Question
Clients generally obtain information from objects of interest (the subject) by calling the subjects methods But how can the client keep current if the subject keeps changing?
How do they know when to query the subject?

The Observer Pattern


Allows an object to be tracked (observed) by an arbitrary number of observers with a minimum of coupling AKA Publisher-Subscriber Think of newspapers or online alerts (like RSS feeds)
You subscribe to get notifications You can unsubscribe at any time

Weather-O-Rama
A weather station periodically measures temperature, humidity, and barometric pressure A driver object is provided that monitors the station and calls a certain method at regular intervals with new data:
void measurementsChanged( );

We need to write code that notifies observers


And the type and number of observers can change!

Humidity Sensor

Display 1

updates

Temperature Sensor

Weather Station

polls

Weather Data Object

updates

Display 2

updates

Pressure Sensor

Display 3

Nave Solution
Add code to measurementsChanged that notifies the observers
There are three initially:
Current conditions Statistics Forecast

See next slide

public void measurementsChanged() { float temp = getTemperature(); float humidity = getHumidity(); float pressure = getPressure(); currentConditionsObserver.update(temp, humidity, pressure); statisticsObserver.update(temp, humidity, pressure); forecastObserver.update(temp, humidity, pressure); }

What potential design liabilities do you see?

Is this a Flexible Design?


Since we know upfront that the observers are not fixed, our design is inadequate There is too much coupling between the Weather object and the observing devices
As new devices are added, well need to change the code in measurementsChanged

What principles of design should we observe?

The Observer Pattern


Sketch
Subject +addObserver(in Observer) +removeObserver(in Observer) +notify() -observers interface Observer +update()

1 ConcreteSubject -subjectState +getState()

1 ConcreteObserver -subject -observerState +update()

The Observer Pattern


Advantages

Both sides are insulated form implementation details


Details in concrete classes can vary independently

New observers can be added at will Subject doesnt change when new types of observers are created

Weather-O-Rama with Observer


Subject +addObserver(in Observer) +removeObserver(in Observer) +notify() -observers 1 * interface Observer +update() DisplayElement +display()

WeatherData +addObserver() +removeObserver() 1 +notify() 1 1

CurrentConditions +update() +display() 1 -subject

StatisticsDisplay +update() +display() 1 -subject

ForecastDisplay +update() +diaplay()

-subject

Implementation Notes
The Subject maintains a list of Observers
Added when observers register

All observers are notified


When? What about composite updates? What about threading issues?

Observers keep a reference to the subject


So they can unsubscribe
By calling subject.removeObserver(this) So they can query state

Notifying Observers
The notify method calls update for each observer How should observers respond? What about passing data to the observers?

The Pull Model


The Subject just notifies the observers without passing any data The Observers then call getter methods on the Subject for data
Observers must know the interface for Subject Have to figure out what changed themselves

The Push Model


The Subject passes data in a parameter in update
As a single instance of Object in Java
For genericity Must use an explicit class or a template parameter in C++

Observers must know how to cast and/or interpret this data


See Program7Gui.ProducerPrinter( )

Makes Observers less reusable


More coupling with Subject

The Observer Pattern


Advantages

Both sides are insulated form implementation details


Details in concrete classes can vary independently

New observers can be added at will Subject doesnt change when new types of observers are created

Pizza in Objectville
public Pizza orderPizza() { Pizza pizza = new Pizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } // 1 type only!

What if we want to make multiple types of pizza?

More Pizza in Objectville


public Pizza orderPizza(String type) { Pizza pizza; if (type.equals(cheese)) pizza = new CheesePizza(); else if (type.equals(greek)) pizza = new GreekPizza(); (etc.) pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box();

return pizza;
}

Here We Go Again!
As new pizza types arrive, we must change this code
If this is the only place it occurs, its not the end of the world Nonetheless, lets try to

Separate those things that vary from those that dont (again) And now that we know about Open-Closed:
Lets try to make this code extensible while being closed to modification

A Pizza-Creating Class
public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; }

Refactoring orderPizza( )
public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; } public Pizza orderPizza(String type) { Pizza pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }

A Pizza-Creating Class
public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; }

A Pizza-Creating Class
public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; }

A Pizza-Creating Class
public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; }

A Pizza-Creating Class
public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; }

A Pizza-Creating Class
public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; }

A Pizza-Creating Class
public class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null; if (type.equals("cheese")) { pizza = new CheesePizza(); } else if (type.equals("pepperoni")) { pizza = new PepperoniPizza(); } else if (type.equals("clam")) { pizza = new ClamPizza(); } else if (type.equals("veggie")) { pizza = new VeggiePizza(); } return pizza; }

2003-2004 Microsoft Corporation. All rights reserved.


This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.

Anda mungkin juga menyukai