1 of 31

Principles of Software Construction: Objects, Design, and Concurrency��Design Practice��Hammad Ahmad and Jeremy Lacomis

1

17-214/514

2 of 31

Administrivia

  • HW2 is due Monday at 11:59pm
    • No late days or resubmissions for HW2a and b!

  • Midterm 1 is next Wednesday (Feb 12) during normal class hours in this room. We will post a practice exam on Piazza later today.
    • You are allowed notes on 4 sheets of paper front and back any font size; feel free to collaborate.

2

17-214/514

3 of 31

What did we talk about on Monday?

3

17-214/514

4 of 31

Learning goals

Explain the decorator pattern in typical terms and recognize/understand when and how to apply it (especially in terms of the way it addresses certain limitations of inheritance).

Practice reasoning about a software design problem, recognizing how and where to consider using patterns, and gain confidence with techniques discussed in class so far.

4

17-214/514

5 of 31

Decorator Pattern

5

17-214/514

6 of 31

Limitations of inheritance

  • Suppose you want various extensions of a Stack data structure…
    • UndoStack: A stack that lets you undo previous push or pop operations
    • SecureStack or LockedStack: A stack that requires a password to let you access the data
    • SynchronizedStack: A stack that serializes concurrent accesses

6

17-214/514

7 of 31

Limitations of inheritance

  • Suppose you want various extensions of a Stack data structure…
    • UndoStack: A stack that lets you undo previous push or pop operations
    • SecureStack or LockedStack: A stack that requires a password to let you access the data
    • SynchronizedStack: A stack that serializes concurrent accesses
    • SecureUndoStack: A stack that requires a password to let you access the data, and also lets you undo previous operations
    • SynchronizedUndoStack: A stack that serializes concerrent accesses, and also lets you undo previous operations
    • SecureSynchronizedStack: …
    • SecureSynchroniedUndoStack: …

Goal: arbitrarily composable extensions

7

17-214/514

8 of 31

Limitations of inheritance

Cannot combine features

Intermediate functionality required

8

17-214/514

9 of 31

Workarounds?

Combining hierarchies?

  • Combinatorial explosion
  • Massive code replication

9

17-214/514

10 of 31

Workarounds?

Multiple Inheritance?

  • Diamond Problem:�Which push() should UndoSecureStack inherit?

10

17-214/514

11 of 31

Decorator Pattern

  • Problem: Responsibilities should be added to an object dynamically at run-time
  • Solution: Defines a Decorator object that implements the interface of an extended object, optionally performing additional functionality before/after forwarding the request
  • Consequences:
    • More flexibility than standard inheritance
    • Avoids feature-laden classes high up in the hierarchy
    • Introduces lots of little objects that all look similar: easy to customize if you understand them, but harder to learn and debug

11

17-214/514

12 of 31

The Decorator design pattern

Common interface for both wrappers and wrapped objects

Class of objects being wrapped. Defines basic behavior that can be altered by decorators

Define extra behaviors that can be added to components dynamically. Override methods of the base decorator and execute their behavior either before or after calling the parent method.

Has a wrappee field for referencing wrapped objects. The type is the interface so it can contain both concrete components and decorators. The base decorator delegates all operations to the wrapped object.

The client can wrap components in multiple layers of decorators, as long as they work with all objects via the component interface.

12

17-214/514

13 of 31

Using the Decorator for our Stack example

13

17-214/514

14 of 31

The Decorator design pattern

  • Applicability
    • To add responsibilities to individual objects dynamically and transparently
    • For responsibilities that can be withdrawn
    • When extension by subclassing is impractical
  • Consequences
    • More flexible than static inheritance
    • Avoids large classes in the hierarchy
    • Lots of little objects

14

17-214/514

15 of 31

Decorators from java.util.Collections

  • Helper methods in java.util.Collections:
    • static List<T> unmodifiableList(List<T> lst);
    • static Set<T> unmodifiableSet( Set<T> set);
    • static Map<K,V> unmodifiableMap( Map<K,V> map);
  • Turn a mutable list into an immutable list
    • All mutation operations on resulting list throw UnsupportedOperationException
  • Similar for synchronization:
    • static List<T> synchronizedList(List<T> lst);
    • static Set<T> synchronizedSet( Set<T> set);
    • static Map<K,V> synchronizedMap( Map<K,V> map);

15

17-214/514

16 of 31

The UnmodifiableCollection (simplified excerpt)

public static <T> Collection<T> unmodifiableCollection(Collection<T> c) {

return new UnmodifiableCollection<>(c);

}

class UnmodifiableCollection<E> implements Collection<E>, Serializable {

final Collection<E> c;

UnmodifiableCollection(Collection<> c) { this.c = c; }

public int size() { return c.size(); }

public boolean isEmpty() { return c.isEmpty(); }

public boolean contains(Object o) { return c.contains(o); }

public Object[] toArray() { return c.toArray(); }

public <T> T[] toArray(T[] a) { return c.toArray(a); }

public String toString() { return c.toString(); }

public boolean add(E e) { throw new UnsupportedOperationException(); }

public boolean remove(Object o) { throw new UnsupportedOperationException(); }

    public boolean containsAll(Collection<?> coll) { return c.containsAll(coll); }

public boolean addAll(Collection<? extends E> coll) { throw new UnsupportedOperationException(); }

public boolean removeAll(Collection<?> coll) { throw new UnsupportedOperationException(); }

public boolean retainAll(Collection<?> coll) { throw new UnsupportedOperationException(); }

public void clear() { throw new UnsupportedOperationException(); }

}

16

17-214/514

17 of 31

Design Practice!

17

17-214/514

18 of 31

Trouble Rules

  • 2-4 Players are trying to go from their home to their respective finish zone.
  • Each turn, players roll a six-sided die and move their pieces clockwise around the board. Rolling a 6 lets them take another turn.

Home

Finish

18

17-214/514

19 of 31

Trouble Rules

  • Players start with their pieces in their home positions. A player must roll a 6 to move a piece from their home position to their start position, but may do so optionally if they have other pieces on the board.
  • A player may not move a piece from the home position to the start position if one of their pieces is already in the start position.

19

17-214/514

20 of 31

Trouble Rules

  • Pieces do not block others from moving.
  • Landing on an opponent’s piece sends them back to their home.

Rolling a 4 means the green player can move to the last empty space

Rolling a 3 means that the green player can move to where the red player’s peg piece is, sending it back to the red home

20

17-214/514

21 of 31

Trouble Rules

  • Once a piece is in its finish zone it is safe and cannot be returned to its home.
  • The exact number must be rolled when moving pieces into the finish zone.
  • The first player to have all of their pieces in their own finish zone is the winner.

Finish

21

17-214/514

22 of 31

Trouble Rules Summary

2-4 players are trying to move their pieces from their home to their finish zone. Players roll a D6 and move their pieces clockwise, rolling a 6 lets them roll again. To exit their home zone, they must roll a 6 and move a piece from their home to their start position. Landing on an opponent’s piece sends it back to the opponent’s home zone. Players may not have two of their pieces in the same position. Exact rolls are required when moving to the finish zone. The first player to have all of their pieces in their own finish zone is the winner.

22

17-214/514

23 of 31

Trouble Rules Summary

2-4 players are trying to move their pieces from their home to their finish zone. Players roll a D6 and move their pieces clockwise, rolling a 6 lets them roll again. To exit their home zone, they must roll a 6 and move a piece from their home to their start position. Landing on an opponent’s piece sends it back to the opponent’s home zone. Players may not have two of their pieces in the same position. Exact rolls are required when moving to the finish zone. The first player to have all of their pieces in their own finish zone is the winner.

23

17-214/514

24 of 31

Domain Model

24

17-214/514

25 of 31

Domain Model

25

17-214/514

26 of 31

Domain Model

26

17-214/514

27 of 31

System Sequence Diagram

27

17-214/514

28 of 31

System Sequence Diagram

28

17-214/514

29 of 31

Object Model

29

17-214/514

30 of 31

Interaction Diagram

30

17-214/514

31 of 31

Summary

  • The decorator pattern can be a good choice if you want to arbitrarily combine/add features to a class.
  • Design is hard!
    • No such thing as “the correct design”...
    • But there are many incorrect designs!

31

17-214/514