Software Architecture
Spring 2022
More
Design Patterns
Structure of the Day
-
"Wrapping" Patterns
-
Activity: Learn a Pattern!
-
Example: Adapter
-
Decorator, Facade, Proxy, Mediator
-
-
Activity: Teach a Pattern!
Objectives
-
Research/learn new design patterns
-
Contrast different design patterns
https://www.flickr.com/photos/hobo4evar/51859595715/

Design Patterns
Most design patterns work by following the same general process:
-
Identify the part of the program that changes (algorithm, state, method, constructor, etc)
-
Encapsulate that functionality into a class
-
Make instances of the new class components (instance variables) of the original class
Wrap it up!
And now...
some "wrapper" patterns!
Pattern Research Sources
"The Book": Gamma et al
http://bit.ly/design-patterns-gof (Ch 4-5)
"The Book": Gamma et al
http://bit.ly/design-patterns-gof (Ch 4-5)
Adapter Pattern
Demo:
Researching the Adapter
GoF 139
Adapter Intent (Solution)
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
Adapter Applicability
-
You want to use an existing class, and its interface does not does not match the one you need.
-
you want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don’t necessarily have compatible interfaces.
Example: Ducks Again
Turkeys
Example: Ducks and Turkeys
abstract class Duck {
quack() {}
fly() {}
}
class Turkey {
gobble() {}
fly() {} //only short distances
}
function runPondSim() {
const ducks: Duck[] = []; //things with the Duck interface
ducks.push(new Turkey()); //DOES NOT COMPILE :(
//Different interfaces
//... lots of work, including:
for(const duck of ducks) {
duck.quack();
duck.fly();
}
}
Example Solution:
Example Solution:
//is a duck!!
class TurkeyAdapter extends Duck {
constructor(private turkey: Turkey){}
quack() {
this.turkey.gobble();
}
fly() {
this.turkey.fly();
}
}
function runPondSim() {
const ducks: Duck[] = [];
ducks.push(new TurkeyAdapter(new Turkey())); // YAY!
for(const duck of ducks) {
duck.quack();
duck.fly();
}
}
Adapter Structure
Consequences
-
How much adapting does an Adapter do?
-
Can we build around it to avoid the need?
-
Can have two-way adapters
Your turn!
Learn a Pattern!
Your task: In a group, research and learn one of the following patterns (assigned): Decorator (175), Facade (185), Proxy (207), or Mediator (273)
Each person in the group should be able to communicate:
-
What is the pattern for?
- Be able to give a 3-minute summary!
-
How do is the pattern implemented?
- Create/find a simple "source code" example!
-
When do I choose this pattern over another?
- Be ready to compare!
Fill in the slides to help: https://docs.google.com/presentation/d/
19gmat_5dxgfIkIqJrhZ4hJGGfzZkIRrqeSvx49IR4cI/edit?usp=sharing
Teach a Pattern!
Your task: Reform (jigsaw) groups with one person who knows each pattern.
Teach your pattern to your new group!
- Make sure everyone understands these at a basic level
Decorator Pattern
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
Facade Pattern
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
Proxy Pattern
Provide a surrogate or placeholder for another object to control access to it.
Mediator Pattern
Define an object that encapsulates how a set of objects interact. Promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

What is the difference between
-
Adapter vs. Decorator?
-
Adapter vs Facade?
-
Adapter vs. Mediator?
Discussion
Adapter vs Facade
-
Adapter converts one interface into another
-
Facade provides a new simpler interface
-
Decorator adds new behavior to same interface
"Adapter gives you what you need, Facade gives you what you want"
vs Decorator
Difference is in the intent and how we talk about the idea of "wrapping"!
Proxy vs Adapter
vs Decorator vs Facade
-
Adapter changes the interface, Proxy forwards the interface
-
Decorator adds behavior, Proxy controls access
-
Proxy chooses result of same interface, decorator adds behavior to same interface
-
-
Facade adds simple interface, Proxy controls use of same interface
Difference is in the intent and how we talk about the idea of "wrapping"!
Mediator vs. ...the rest
-
Mediator is a behavioral pattern, not a structural pattern!
-
Adapter translates an interface, Mediator separates the interface entirely
-
Facade abstracts specific functionality, Mediator abstracts arbitrary communication;
-
etc...
Discussion: Which Pattern?
What pattern is being used by the Private Route pattern (e.g., react-router v5)?
function PrivateRoute(props) {
//...determine if user is logged in
if(userIsLoggedIn) { //show the normal route
return <Route {...props} />
}
else { //otherwise, redirect
return <Redirect to="/" />
}
}
function App(props) {
return (
<Switch>
<Route exact path="/">
<Static.WelcomePage user={currentUser} />
</Route>
<Route path="/signin">
<SignInPage user={currentUser} loginFunction={loginUser} />
</Route>
<PrivateRoute path="/profile" user={currentUser}>
<ProfilePage user={currentUser} />
</PrivateRoute>
</Switch>
)
}Discussion: Which Pattern?
What pattern is being used by higher-order components?
//https://www.robinwieruch.de/react-hooks-higher-order-components/
//higher-order functions
const withError = function(Component) {
return function(props) {
if (props.error) {
return <div>Something went wrong ...</div>;
}
return <Component {...props} />;
}
};
//combine functions
const DataTableWithFeedback = compose(withError, withLoading)(DataTable);
//render
function App(props) {
//...
return (
<DataTableWithFeedback columns={columns} data={data} error={error} isLoading={isLoading} />
);
};Discussion: Which Pattern?
What pattern is being used by higher-order components?
//example from old react-redux documentation!
const mapStateToProps = (state, ownProps) => ({
// ... computed data from state and optionally ownProps
})
const mapDispatchToProps = {
// ... normally is an object full of action creators
}
// `connect` returns a new function that accepts the component to wrap:
const connectToStore = connect(
mapStateToProps,
mapDispatchToProps
)
// and that function returns the connected, wrapper component:
const ConnectedComponent = connectToStore(Component)
// We normally do both in one step, like this:
connect(
mapStateToProps,
mapDispatchToProps
)(Component)ACTION ITEMS!
For Next Time
-
Project 2 Checkpoint (Draft) due Sunday
-
Reading for the week:
-
Design Patterns Explained (Trott) (pattern motivation)
-
Gamma et al. (introduction)
-
Reference readings are for reference/details only
-
-
Reading Quiz 7 (due Sunday)
Context: Ducks with powers
Some ducks should be able to do more than just quack and swim.
Wear a hat
Wear a cape
Join a rock band
info443-wi22-design-patterns-2
By Joel Ross
info443-wi22-design-patterns-2
- 494