# CSC 321.01, Class 19: Design patterns

Overview

• Preliminaries
• Notes and news
• Upcoming work
• Extra credit
• Questions
• Why design patterns?
• Flyweight
• Iterator
• Adaptor / Decorator / Wrapper

## Preliminaries

### Upcoming work

• HW9: Document a Design Pattern due Tuesday at 9:00 p.m.
• Goal: Clear explanation, with examples. I will have you talk about your example in class.
• 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

### Good things to do (Academic/Artistic)

• Faulconer gallery has two great exhibits.
• Tuesdsay Extra

## Why design patterns?

• Much of the work we do involves discovering and using patterns.
• E.g., to do something to each element of a list in Scheme, you might write
(define proc
(lambda (lst)
(if (null? lst)
null
(cons (something (car lst))
(proc (cdr lst))))))

• In some sense, these are just techniques for approaching problems.
• Here’s a pattern for writing safer comparisons in C.
• if (CONST == VAR) { ... } is better than if (VAR == CONST) { ... }
• if (5 == x) { ... }
• if (x = 5) { ... }
• About three decades ago, Christopher Alexander wrote a book entitled “A Pattern Language” about the design of houses.
• About two and a half decades ago, a group of OO software designers thought that a similar approach for OO software design.
• Describe problem domains and the way experts tend to approach them, so that novices can learn to write better architected systems
• “Design Patterns” - The name they came up for this idea.
• Multiple approaches to the traditional design patterns
• Intended as “Here’s a way to think about the problem.”
• Also works as a way of discussing a solution (or the design of a system).
• Unfortunately, sometimes treated as an absolute.
• Many languages now incorporate design patterns in the design of the language. For example, Java has iterators. Rails has MVC.
• A good design pattern usually has at least four parts. (Yes, I’ll do examples.)
• The problem that the pattern addresses.
• The “good”/recommend/experienced solution and/or philosophy of how to approach the problem
• Examples, which ground the idea
• A diagram which shows the relationship between the classes.

## Flyweight

Problem: We have expensive/large/etc. state data. We have lots of objects.

Solution: As much as possible, decouple the state from each object.

Example: Typography (or even just getting letters on the screen)

• We will be drawing sequences of characters on the screen.
• So we have something like the following
class Line {
Character[] contents;
}

class Character {
int x;
int y;
BigBunchOfData thisCharacterAt12pt;
BigBunchOfData thisCharacterAt14pt;
BigBunchOfData thisCharacterAt16pt;
BigBunchOfData thisCharacterAt18pt;
BigBunchOfData thisCharacterAt22pt;

public drawYourself(Screen screen) {
...
}
}


We can move the instructions for drawing the character outside of the character itself.

class Character {
int x;
int y;
CharacterData data;
public drawYourself(Screen screen) {
data.drawYourselfAt(screen, x, y);
}
}

class CharacterData {
BigBunchOfData thisCharacterAt12pt;
BigBunchOfData thisCharacterAt14pt;
BigBunchOfData thisCharacterAt16pt;
BigBunchOfData thisCharacterAt18pt;
BigBunchOfData thisCharacterAt22pt;

public drawYourSelfAt(Screen screen, int x, int y) {
...
}
}


We’ve traded an extra procedure call for a big savings in storage.

Construction is now a bit harder.

It used to be: Make a new Character. Load the character data for that character from wherever. Now it’s _Make a new object. Find the associated heavyweight object. Link to it.

## Iterator

Problem: I want to do so something to each element of a collection.

Traditional bad approach: Each collection provides its own mechanism for dealing with iteration.

for (i = 0; i < A.size; i++) {
doSomethingTo(A[i]);
}

tmp = L.front;
while (tmp != null) {
doSomethingTo(tmp.val);
tmp = tmp.next;
}


Meta problem: The code looks different.

• Cognitive overload: You’re doing the same thing, why does it look different? Code for similar goals should look the same.
• Substitution is not easy.
• No encapsulation

Philosophy/Approach: Rather than having a custom approach for each collection, have collection return an object that allows the consumer to iterate the values.

Note: Designing the Iterator interface is hard and may be context dependent.

public interface Iterator<T> {
T current();
void next();
boolean hasNext();
}

public interface Iterator<T> {
T getNext() throws NoMoreElementsException;
}


Diagram:

Problem: I need X. I have a Y. Y is a lot like X.

Example: I need a first-in first-out to-do list. I have a Queue. How do I use my Queue as a to-do list?

public class Queue {
public void enqueue(String val);
public String dequeue();
public boolean empty();
}

public interface ToDoList {