CSC 321.01, Class 20: Design patterns, continued
Overview
- Preliminaries
- Notes and news
- Upcoming work
- Extra credit
- Questions
- Exploring more patterns
- A process
- An example
- The patterns
Preliminaries
News and notes
- Please sit with your pattern group
- Factory (any kind is fine): FA, SG, JM, JZ
- Observer: MB, MG, AM, AM
- Proxy: EB, BH, DN, MD
- Strategy: GC, PK, JS, JRL
- Template Method: WSC, NA, RS
- Stickers.
- There were a lot of problems with the pattern writeups. So I’m going to approach today’s class a bit differently than I’d planned. I’d also like you to rewrite your assignments to meet the (insufficiently well stated) goals.
- Friday is our last CSC 321 class. So sad. But we’ll be together in CSC 322.
Upcoming work
- Revised HW9: Document a Design Pattern due
before spring break.
- Make sure you have the problem, bad solutions, the pattern-based solution, and examples.
Good things to do (Academic/Artistic)
- Faulconer gallery has two great exhibits.
- Thursday Extra
Good things to do (Other)
- Play on campus.
- WGMC on Thursday at 6pm. Write a mission statement.
- Little Mermaid Musical at HS.
Questions
How will you grade us?
Homework: Percent submitted on time * .90 + bonus for great answers
Journals: Percented submitted on time * .90 + bonus for great answers - loss for mediocre answers
Participation: .90 +/- noticably good or noticably mediocre
_Will we get feedback beyond the regular “Here are some really <word that Sam won’t say in class> answers and here are some really good ones?”
Only on the design patterns.
Will you let us argue our grades?
It seems like a bad idea, but probably.
Five patterns
How we’ll approach it
- What is the underlying problem the pattern is intended to solve. (You may also want to give a realistic example.)
- Pause: Everyone think about how you tend to approach those problems.
- What does the pattern say a better way to solve that problem is?
My Adapter example
- The problem: When I design a large software system, I specify the
interfaces for all the components. While none of the components
already exist, some things are similar.
- E.g., “Workflow manager” needs a “quick FIFO to-do-list
- QuickFIFOToDoList Needs methods addTask, nextTask, done?
- Queue
provides enqueue, dequeue, empty?
- A typical solution:
- We know how to implement queues, so just implement QuickFIFOToDoList
using the strategy we’ve always used for implementing queues. (E.g.,
linked list with pointers to both ends.)
- Reinventing the wheel is rarely a good idea, unless you really need different behavior.
- Use the Queue
that's already built in to Java: Everytime that QuickFIFOToDoList appears in WorkFlowmanager, replace it with `Queue `. (Similar search and replace on method names.) - Obscures our code.
- Makes changes harder
- We know how to implement queues, so just implement QuickFIFOToDoList
using the strategy we’ve always used for implementing queues. (E.g.,
linked list with pointers to both ends.)
- The adapter solution: Write a really simple class that delegates most of the work to another class.
For our example
public class MyQuickFIFOToDoList implements QuickFIFOToDoList {
Queue<Strings> core;
public String nextTask() {
return core.dequeue();
}
public void addTask(String task) {
core.enqueue(task);
}
}
This strategy lets us plan for the future. If we need to make any changes to semantics in QuickFIFOToDoList, they are localized to this one class. Plus our code is more readable.
The problems these patterns address
Factory How to create objects on the fly from one of many subclasses with the decision made at run time rather than compile time? Example: A video game needs to spawn monsters and the monsters change over time (different levels, etc.).
Observer We work in a world in which there is a subject and one or more observers. The observers need to know when the subject changes. MVC: If the model changes, the view should change. (E.g., Facebook)
Proxy You have an object that is expensive to create. You should only create the object when it’s really needed by the client. Or you want to enforce preconditions. The client still needs something to refer to, even thought it may not be completely needed.
Strategy Different algorithms can be appropriate for the same problem. For example, if we have a small list, we might use insertion sort and if we have a long list, we might use merge sort. The algorithm needs to be decided at run time, not compile time.
Template Method. You have multiple algorithms and you’d like to
factor out the similarity in the algorithms. Or You have one algorithm,
but you can make it behave differently using other functions as input.
(E.g., sort
in Scheme can behave differently depending on the comparator
you give it.)
How we typically address these problems
Talk about the two that come immediately after your group (cycle around to the front). What would you do if you encountered that design issue when impelemnting a program?
We’ll look at how Sam remembers approaching each of these problems when he first encountered them.
Factory
A really big conditional
r = random(100);
if (level == 1)
if (r < 20)
return new WaterBottle();
else if (r < 40)
return new ExpoMarker();
else
return new Eraser();
else if level (== 2)
if (r <30)
return new LinuxWorkstation(50 + random(10));
...
Problem:
* Hard to read
* Hard to change at run time
* Not very modular
**Observer**
A busy loop
while (true) { if (subject.lastUpdated > lastUpdated) { lastUpdated = subject.lastUpdated(); showCurrentState(subject); } } ```
Proxy
Make the client pay attention to when it has an incomplete object (and it’s okay to do so) and when it needs the costly/heavyweight object.
Strategy
Curse Java for not being Scheme.
Template Method
Curse Java for not being Scheme.
How the patterns address the problem
Factory
Observer
Proxy
Strategy
Template Method