150 likes | 264 Views
Decorator. COMP 401, Spring 2012 Lecture 18 3/21/2013. A motivating example: SongLog. Goal: Create an object to represent a song “log” (i.e., record of what songs were played) Provide ability to answer queries about songs played. Design: void recordInLog(SongInterface s )
E N D
Decorator COMP 401, Spring 2012 Lecture 18 3/21/2013
A motivating example: SongLog • Goal: • Create an object to represent a song “log” (i.e., record of what songs were played) • Provide ability to answer queries about songs played. • Design: • void recordInLog(SongInterfaces) • void recordInLog(SongInterfaces, Date time) • Date lastPlayed(SongInterfaces) COMP 401 :: Spring 2012
Date • Java’s class for dealing with Date • Represents a point in time down to millisecond precision. • Separate classes for formatting and calendar operations. • Calendar • DateFormat • Provides a number of pre-defined formats • SimpleDateFormat • Allows you to construct customized formats • See Date tutorial on Oracle site for more. COMP 401 :: Spring 2012
SongLog version 1 • lec18.v1 • Strategy: • Maintain two array lists • One for songs • One for dates COMP 401 :: Spring 2012
SongLog v1 critique • It works, but not as clean as it could be. • Why? COMP 401 :: Spring 2012
Decorator Pattern • Useful when you want to add additional state or functionality to a class without formally subclassing. • When might that be? • Additional state/functionality is auxiliary to object’s main purpose. • Additional state/functionality is local to a collection or some other class encapsulating the object. • SongLog for example. • As a workaround for multiple inheritance • Want to build up an object with subsets of different functionality. • Decorator pattern is a form of delegation. COMP 401 :: Spring 2012
Decorator Pattern Recipe • Setting up: • Start with original interface. • If decorating a class without an interface, refactor original class to have an interface. • In our example: • Song (this is the interface) • SongImpl COMP 401 :: Spring 2012
Decorator Pattern Recipe • Step 1: • Extend interface, declaring additional functionality. • In our example: • LoggedSong • Date getDate(); COMP 401 :: Spring 2012
Decorate Pattern Recipe • Step 2: • Create class that implements decorated interface. • Provide constructor that takes an object of the original (i.e., undecorated) interface type and possibly any additional state information needed for decorated behavior. • Delegate original interface methods to encapsulated object. • Provide implementations for decorated behavior. • In our example: • LoggedSongImpl • public LoggedSongImpl(Song s, Date d) • Date getDate() COMP 401 :: Spring 2012
SongLog v2 • This version decorates the songs as logged songs and then stores them. COMP 401 :: Spring 2012
Decorator Avoids Subclassing • Decorator applies to interfaces (not classes). • Caveat: as I am teaching it here. • It’s the interface that is being decorated. • Subinterfacing is distinct from subclassing • Both are types of inheritance, but not the same • This is why we encounter statements like: • Decorators provide a flexible alternative to subclassing for extending functionality. • See Decorator in Java tutorial from Abhi On Java link in readings. • This is why we needed Song to be an interface with an accompanying class (i.e., SongImpl) implementation. COMP 401 :: Spring 2012
Decorator Illustrated interface I { void do_something(); } class C implements I { void do_something() { ... } } class DC implements DI { private I wrapped_i; public (I i_obj) { wrapped_i = i_obj; } void do_something() { wrapped_i.do_something(); } void do_more() { ... } } interface DI extends I { void do_more(); } COMP 401 :: Spring 2012
Unwrapping the Decorator • When you decorate an existing object, you are creating a new object. • Existing object is inside. • Might need to have the ability to “undecorate” the object. • For example, if we need to give it back to someone who expects the original. • lec18.v3 COMP 401 :: Spring 2012
Undecorating • Provide method to get back original in decorated interface. interface I { void do_something(); } class C implements I { void do_something() { ... } } class DC implements DI { private I wrapped_i; public (I i_obj) { wrapped_i = i_obj; } public I getWrapped() { wrapped_i; } void do_something() { wrapped_i.do_something(); } void do_more() { ... } } interface DI extends I { void do_more(); I getWrapped(); } COMP 401 :: Spring 2012
Assignment 5 • You can add new state to piece subclasses if you need / want to. • But you shouldn’t have to. • You can create new methods in the parent class as helpers for your subclasses. • Be sure to mark as “protected” to provide access. • HINT: This might be useful for checking line of sight path between start and finish.