KEMBAR78
Software System Architecture-Lecture 6.pptx
Strategy:
A Behavioral Design
Pattern
What is a Design Pattern?
A design pattern deals with interactions between individual software components
They are recurring solutions to common problems of design!
Strategy
 Define a family of algorithms
 Encapsulate each one
 Make them interchangeable
In a Strategy design pattern, you will:
You should use Strategy when:
 You have code with a lot of algorithms
 You want to use these algorithms at different times
 You have algorithm(s) that use data the client should not know about
Strategy Class Diagram
Context
contextInterface()
Strategy
algorithmInterface()
ConcreteStrategyC
algorithmInterface()
ConcreteStrategyB
algorithmInterface()
ConcreteStrategyA
algorithmInterface()
Strategy vs. Subclassing
 Strategy can be used in place of subclassing
 Strategy is more dynamic
 Multiple strategies can be mixed in any combination where subclassing would
be difficult
Subclassing
Class
functionX()
SubClass1
functionX()
SubClass2
functionX()
SubClass3
functionX()
Add a function
Class
functionX()
functionY()
SubClass1
functionX()
SubClass2
functionX()
SubClass3
functionX()
Add functionY()
What happens?
Class
functionX()
functionY()
SubClass1
functionX()
functionY()
SubClass2
functionX()
functionY()
SubClass3
functionrX()
functionY()
SubClass2.1
behaviorY()
SubClass2.2
behaviorY()
Need SIX classes to
handle both functions!!!
Strategy makes this easy!
Class
functionX()
functionY()
StrategyX
functionX()
...
StrategyY
functionY()
...
Benefits of Strategy
 Eliminates conditional statements
 Can be more efficient than case statements
 Choice of implementation
 Client can choose among different implementations with different space and time
trade-offs
Benefits of Strategy
 Families of related algorithms
 Alternative to subclassing
 This lets you vary the algorithm dynamically, which makes it easier to change and
extend
 You also avoid complex inheritance structures
Drawbacks of Strategy
 Clients must be aware of different strategies
 Clients must know how strategies differ so it can select the appropriate one
 Communication overhead between strategy and context
 Sometimes the context will create and initialize parameters that are never used
Drawbacks of Strategy
 Increased number of objects
 if the algorithm differences are simple, the extra classes add extra complexity
Factory Pattern
Building Complex Objects
New is an implementation
 Calling “new” is certainly coding to an implementation
 In fact, it’s always related to a concrete class
 (Open for Modification)
 That’s fine when things are simple, but . . .
Look Out For Change
 When you have several related classes, that’s probably a good sign
that they might change in the future
Duck duck;
if (picnic) {
duck = new MallardDuck();
} else if (hunting) {
duck = new DecoyDuck();
} else if (inBathTub) {
duck = new RubberDucky();
}
Design Principle
 What should you try to do with code that changes?
When Building Objects is Complex
 Book example - a variety of types of pizzas
 Think about constructing the weapons in your decorator lab
Pizza orderPizza() {
Pizza pizza = new Pizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
Pizza orderPizza(String type) {
Pizza pizza;
if (type.equals(“cheese”)) {
pizza = new CheesePizza();
} else if (type.equals(“greek”)) {
pizza = new GreekPizza();
} else if (type.equals(“pepperoni”)) {
pizza = new PepperoniPizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
Pizza orderPizza(String type) {
Pizza pizza;
if (type.equals(“cheese”)) {
pizza = new CheesePizza();
} else if (type.equals(“greek”)) {
pizza = new GreekPizza();
} else if (type.equals(“pepperoni”)) {
pizza = new PepperoniPizza();
} else if (type.equals(“sausage”)) {
pizza = new SausagePizza();
} else if (type.equals(“veggie”)) {
pizza = new VeggiePizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
Pizza orderPizza(String type) {
Pizza pizza;
if (type.equals(“cheese”)) {
pizza = new CheesePizza();
} else if (type.equals(“greek”)) {
pizza = new GreekPizza();
} else if (type.equals(“pepperoni”)) {
pizza = new PepperoniPizza();
} else if (type.equals(“sausage”)) {
pizza = new SausagePizza();
} else if (type.equals(“veggie”)) {
pizza = new VeggiePizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
Encapsulate!
public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza;
if (type.equals(“cheese”)) {
pizza = new CheesePizza();
} else if (type.equals(“pepperoni”)) {
pizza = new PepperoniPizza();
} else if (type.equals(“sausage”)) {
pizza = new SausagePizza();
} else if (type.equals(“veggie”)) {
pizza = new VeggiePizza();
}
return pizza;
}
}
Now orderPizza() is tidy
public class PizzaStore {
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory) {
this.factory = factory;
}
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cute();
pizza.box();
return pizza;
}
}
No new operator
Simple Factory
 Pull the code that builds the instances out and put it into a separate class
 Identify the aspects of your application that vary and separate them from what
stays the same
Simple Factory Pattern
Client
orderProduct()
SimpleFactory
createProduct()
<<abstract>>
Product
productMethod()
ConcreteProductB
ConcreteProductA
ConcreteProductC
Why would we do this?
 Multiple clients needing same types of object
 Ensure consistent object initialization
The Factory Method
Definition:
The factory Method Pattern defines an interface for creating an object, but lets the
subclasses decide which class to instantiate. Factory Method lets a class defer
instantiation to subclasses.
Factory Method Pattern
<<abstract>>
Creator
factoryMethod()
operation()
<<abstract>>
Product
ConcreteCreator
factoryMethod()
ConcreteProduct
abstract!
IS-A
HAS-A
IS-A
No more SimpleFactory class
Object creation is back in our class, but …
delegated to concrete classes
Dependency Inversion Principle
Depend upon abstractions --
not concrete classes
Impossible Guidelines
 No variable should hold a reference to a concrete class
 No class should derive from a concrete class
 No method should override an implemented method of an of its base
classes.
Impossible Guidelines
The idea here is to stay clear of classes that are likely to change
String studentChecking
System businessChecking
Integer FederalTaxCode
What if there are categories of Products?
<<abstract>>
Player
HeroGunner
HeroStealth
HeroTank
HeroPilot
EnemyLevelBoss
EnemyCaptain
EnemyThug
When Subclasses get
out of hand…
•make the factory an abstract class as well
•Instead of subclasses for the products, subclasses for the
components of the products
•The next diagram is overwhelming…
breathe in, breath out
Abstract Factory Pattern
<<interface>>
AbstractFactory
createProductA()
createProductB()
<<interface>>
AbstractProductA
<<interface>>
AbstractProductB
Client
ConcreteFactory1
createProductA()
createProductB()
ConcreteFactory2
createProductA()
createProductB()
ConcreteProductA1
ConcreteProductA2
ConcreteProductB1
ConcreteProductB2
Abstract Factory Pattern
This design favors composition
handy when you need to insure the quality of many similar,
but slightly different versions of a class
More Diagrams
 pp.156/157
 160/161
Summary
 Simple Factory
 Use when you have only one family of objects
 Factory Method Pattern
 Use when you have multiple families of objects
 Abstract Factory
 Use when you have multiple families of object components
The Composit Pattern
Intent
 Compose objects into tree structures to represent part-whole hierarchies.
 Let clients treat individual objects and compositions of objects uniformly.
Motivation
 Some system let user build complex diagrams out of simple components.
 A simple implementation could define classes for each concept of the
components.
 a problem: Code that uses these classes must treat primitive and container objects
differently.
Motivation(2)
 The key of composite pattern is an abstract class that represents both
primitives and their containers.
 A typical composite structures:
aPicture
aPicture aLine aRect
aText aLine aRect
Applicability
 Use this pattern when
 You want to represent part-whole hierarchies of objects.
 You want clients to be able to ignore the difference between compositions of
objects and individual objects. Client will treat all objects in the composite
structure uniformly
Structure
 Page 164
Component
Operation()
Add(Component)
Remove(Component)
GetChild(int)
Leaf
Operations()
Composite
Operation()
Add(Component)
Remove(Component)
GetChild(int)
children
Client
Participants
 Component
 declare the interface for objects in the composition.
 implements default behavior.
 declares an interface for accessing and managing its child components.
 (opt.) defines an interface for accessing a component’s parent in the recursive
structure, …
Participants(2)
 Leaf
 represents leaf objects in the composition.
 define behavior for primitive objects.
 Composite
 defines behavior for components having children.
 stores child components.
 implements child-related operations in the component interface.
 Client
 manipulates objects in the composition through the Component interface.
Collaborations
 Client use the Component class interface to interact with objects in the
composite structure.
 If the recipient is a Leaf, then the request is handled directly.
 If not, the it usually forwards requests to its child components, possibly performing
additional operations before and/or after forwarding.
Consequences
 defines class hierarchies consisting of primitive objects and composite objects.
 makes the client simple.
 makes it easier to add new kinds of components.
 (disadvantage) can make your design overly general.
Sample Code
 Equipment: computer and stereo components.
class Equipment {
virtual ~Equipment();
const char* Name() { return _name;}
virtual Watt Power();
virtual Currency NetPrice();
virtual Currency DiscountPrice();
virtual void Add(Equipment *);
virtual void Remove(Equipment *);
virtual Iterator<Equipment *>* CreaterIterator();
Protected:
Equipment(const char *);
private:
const char* _name;
}
Sample Code
 Leaf class:
class FloppyDisk : public Equipment{
public:
FloppyDisk(const char*);
virtual ~FloppyDisk();
virtual Watt Power();
virtual Currency NetPrice();
Virtual Currency DiscountPrice();
}
Sample Code
 The base class for equip. containing other equip.
class CompositeEquipment: public Equipment{
public:
virtual ~CompositeEquipment();
virtual Watt Power();
virtual Currency NetPrice();
virtual Currency DiscountPrice();
virtual void Add(Equipment *);
virtual void Remove(Equipment *);
virtual Iterator<Equipment *>*CreatIterator();
protected:
CompositeEquipment(const char*);
private:
List <Equipment *> _equipment;
}
Sample Code
 Default Impl. of NetPrice
Currency CompositeEquipment::NetPrice()
{
Iterator<Equipment *> *i=CreateIterator();
Currency total = 0;
for (i->First(); !i->IsDone(); i->Next() {
total += i->CurrentItem()->NetPrice();
}
}
Sample Code
 class for computer chassis
class Chassis: public CompositeEquipment{
public:
Chassis(const char*);
virtual ~Chassis();
virtual Watt Power();
virtual Currency NetPrice();
virtual Currency DiscountPrice();
};
Sample Code
 Use the classes
Cabinet * cabinet = new Cabinet(“PC Cabinet”);
Chassis* chassis = new Chassis(“PC Chassis”);
Cabinet->Add(chassis);
Bus * bus = new Bus(“NCA Bus”);
bus->Add(new Card(“16Mbs Token Ring”));
Chassis->Add(bus);
Chassis->Add(new FloppyDisk(“3.5in Floppy”));
cout << ‘The net price is” <<Chassis->NetPrice() <<endl.

Software System Architecture-Lecture 6.pptx