Title: Peter Coad
1JAVA DESIGNBuilding Better Apps and Applets
- Peter Coad
- Object International, Inc.
- www.oi.com pc_at_oi.com
- 1-919-772-9350 fax -9389
- direct line -7734 direct fax -8916
Version Date Jan. 2, 1998
2Purpose and Agenda
- Purpose
- To gain insights into better design
- Agenda
- 1. Design with Composition, Rather than
Inheritance. - 2. Design with Interfaces.
- 3. Design with Threads.
- 4. Design with Notification.
- 5. Build with Java.
"Building materials profoundly affect design
techniques."
31. Design with Composition, Rather than
Inheritance
- Inheritance extends attributes and methods.
- "Whats the same whats different."
- Weak encapsulation with respect to superclasses
- Awkward accommodation of change over time
- Composition delegates work to other objects.
- Message-based encapsulation
- Gracious accommodation of change over time
4Inheritance Good Uses (i)
MomentInterval
dateTime
number
Purchase
Reservation
amount
dateTimeExpiration
total
notifyPendingExpiration
public abstract class MomentInterval extends
Object /code/ public class Reservation
extends MomentInterval /code/ public class
Purchase extends MomentInterval /code/
5Inheritance Good Uses (ii)
6Inheritance Problems (i)
7Inheritance Problems (ii)
8Inheritance When to Use It
9Composition
public class Passenger extends Object private
Vector reservations /created by constructor/
10Composition and Change (i)
11Composition and Change (ii)
12Combo
132. Design with Interfaces
- A common set of method signatures
- Interfaces let you connect to and message...
- An object in any class that implements that
interface - Rather than an object in a specific class.
public interface IName public String
getName() public void setName(String aName)
interface
public Person extends Object implements IName
public String getName() /code/ public
void setName(String aName) /code/
Person
IName
implementer
14Why Design with Interfaces?
- Abstraction of common method signatures
- Abstract upwards and avoid method signature
overload. - Interaction substitution
- Interact with objects from one class as if it
were an object from another class. - Part substitution
- Unplug an object from one class and plug in an
object from another class.
15Interface Strategies (First Set) --Factor Out
- a. Strategy factor-out common method signatures.
- b. Strategy factor-out proxies.
- c. Strategy factor-out by analogy.
- d. Strategy factor-out future expansion.
16a. Common Method Signatures (i)
- Strategy factor-out common method signatures.
Store
Person
Sale
Customer
number
name
dateTime
number
address
1
n
n
n
1
1
grandTotal
calcTotal
howMuch
howMuch
calcTax
n
1-n
1
1
Item
SaleLineItem
number
quantity
description
1
n
calcTotal
price
calcTax
howMany
17a. Common Method Signatures (ii)
Store
ICount
Customer
Person
Sale
number
howMany
number
name
dateTime
1
n
n
n
1
1
ITotal
address
ICount
ISell
ICount
ITotal
calcTotal
1-n
n
ITax
1
calcTax
1
Item
ISell
SaleLineItem
number
ITotal
quantity
description
ITax
1
n
price
ISell
ICount
public interface ISell extends ITotal, ITax
18b. Proxies (i)
- Strategy factor-out proxies.
Passenger
Person
type
name
IName
number
1
1
address
getName
INameAddress
setName
IAddress
getAddress
setAddress
INameAddress
Person
Passenger
IName
name
type
IAddress
address
number
1
1
INameAddress
INameAddress
19b. Proxies (ii)
INameAddress
NameAddressUI
IName
IAddress
n
display
public class NameAddressUI private Vector
nameAddresses /created by constructor/
public void addNameAddress(INameAddress
aNameAddress) this.nameAddresses.addElemen
t(aNameAddress) public void display()
Enumeration nameAddressList
this.nameAddresses.elements() while
(nameAddressList.hasMoreElements())
String nameAddress (String) nameAddressList.next
Element() /display using
nameAddress.getName()/ /display using
nameAddress.getAddress()/
20c. By Analogy (i)
- Strategy factor-out by analogy.
FlightDescription
hasAvailableSeat
reserveSeat
cancelSeat
IDateReserve
FlightDescription
available (date)
reserve (date, reserver)
IDateReserve
cancel (date, reserver)
21c. By Analogy (ii)
DateReserveUI
IDateReserve
available (date)
invokeAvailable
n
reserve (date, reserver)
invokeReserve
cancel (date, reserver)
invokeCancel
FlightDescription
IDateReserve
22c. By Analogy (iii)
IDateReserve
DailyWorkOrder
available (date)
reserve (date, reserver)
n
reserveResources
cancel (date, reserver)
Equipment
Workspace
Worker
IDateReserve
IDateReserve
IDateReserve
public class DailyWorkOrder private Vector
dateReservables /created by constructor/
public void addDateReserves(IDateReserve
aDateReserve) this.dateReservables.addElem
ent(aDateReserve) public void
reserveResources() Enumeration
dateReservableList this.dateReservables.elements
() while (dateReservableList.hasMoreElement
s()) IDateReserve dateReservable
(IDateReserve) dateReservablesList.nextElement()
dateReservable.reserve()
23d. Future Expansion (i)
- Strategy factor-out for future expansion.
Zone
IActivate
IActivate
n
activate
deactivate
1
Sensor
IActivate
Coad notation UML notation
24d. Future Expansion (ii)
IActivate
Zone
activate
deactivate
n
IActivate
Sensor
IActivate
25d. Future Expansion (iii)
IActivate
Zone
activate
deactivate
n
IActivate
Switch
RobotArm
Motor
Sensor
IActivate
IActivate
IActivate
IActivate
public class Zone private Vector
activatibles /created by constructor/
public void addActivate(IActivate anActivate)
this.activatibles.addElement(anActivate)
public void activate() Enumeration
activatableList this.activatables.elements()
while (activatableList.hasMoreElements())
IActivatable activatable (IActivate)
activatableList.nextElement()
activatable.activate()
26Interface Strategies (Second Set) -- Design-In
- e. Strategy design-in, from features to
interfaces. - f. Strategy design-in, from role to interfaces
to proxies. - g. Strategy design-in, from collections to
interfaces. - h. Strategy design-in, from scenarios to
interfaces. - i. Strategy design-in, from intra-class roles to
interfaces. - j. Strategy design-in, from plug-in methods to
interfaces.
27e. Features to Interfaces (i)
- Strategy design-in, from features to interfaces.
- Look for a common feature, one you need to
provide in different contexts. - Identify a set of common method names that
correspond to that feature. - Add an interface.
- Identify implementers.
Features Total outstanding balances for a
borrower Total outstanding balances for an
applicant. List accounts and limits for a
borrower. List accounts and limits for an
applicant.
28e. Features to Interfaces (ii)
IAccount
totalOustandingBorrowingBalance
listBorrowingAccountsAndLimits
BorrowingAccount
Borrower
Applicant
1
0-1
1
0-1
getBalance
IAccount
IAccount
public interface IAccount public double
totalOutstandingBorrowingBalance() public
Enumeration listBorrowingAccountsAndLimits()
29f. Role to Interface to Proxies (i)
- Strategy design-in, from role to interface to
proxies. - Take a role and turn its method signatures into a
role-inspired interface. - Let a party or a role offer that same interface
by - Implementing that interface, and
- Delegating the real work to the original role
player.
Borrower
totalApprovedLimits
totalAvailableLimits
30f. Role to Interface to Proxies (ii)
Borrower
IBorrow
totalApprovedLimits
totalAvailableLimits
IBorrow
Borrower
Applicant
Party
1
0-1
1
n
IBorrow
IBorrow
IBorrow
Organization
Person
IBorrow
totalApprovedLimits
totalAvailableLimits
31f. Role to Interface to Proxies (iii)
public interface IBorrow public double
totalApprovedLimits() public double
totalAvailableLimits() public Borrower extends
Object implements IBorrow public double
totalApprovedLimits() /real work/ public
double totalAvailableLimits() /real
work/ public Applicant extends Object
implements IBorrow private Borrower
borrower /add/remove with add/remove methods/
public double totalApprovedLimits()
return this.borrower. totalApprovedLimits ()
/delegate/ public double totalAvailableLimit
s() return this.borrower.
totalAvailableLimits () /delegate/
32g. Collections and Members to Interfaces (i)
- Strategy design-in, from collections and members
to interfaces. - Does your object hold a collection of other
objects? If so - Consider its potential method signatures.
- If other collections might offer the same set of
method signatures, then design-in that common
interface. - Is your object a member within a collection? If
so - If that object needs to provide an interface
similar to the collections it is in, then
design-in that common interface. - Identify implementers.
33g. Collections and Members to Interfaces (ii)
ITotalApprovedLimit
totalApprovedLimit
ICompareAppliedVsApproved
compareAppliedVsApproved
Approval
Application
1
n
ITotalApprovedLImit
ITotalApprovedLimit
ICompareAppliedVsApproved
ICompareAppliedVsApproved
34h. Scenarios to Interfaces(i)
- Strategy design-in, from scenarios to
interfaces. - Look for similar interaction patterns.
- Add an interface-implementer column.
- Use this naming convention Iltwhat it doesgt
Implementer - Add an interface Iltwhat it doesgt.
- Identify implementers.
35h. Scenarios to Interfaces (ii)
Name
Assess profit and risk (i).
Application
BorrowingAccount
Applicant
Borrower
Constraints
assessRisk
assessProfit
assessProfit
assessProfit
assessRisk
assessRisk
assessRisk
( profit)
assessProfit
assessProfit
( profit)
assessProfit
assessProfit
n
n
assessProfit
assessProfit
( risk)
assessRisk
assessRisk
n
n
( risk)
assessRisk
assessRisk
assessRisk
assessRisk
n
n
assessRisk
assessRisk
Name
Assess profit and risk (ii).
IAssessProfitAndRisk Implementer
Applicant
Constraints
assessProfit
assessProfit
assessRisk
assessRisk
( profit)
assessProfit
assessProfit
( profit)
assessProfit
assessProfit
( risk)
assessRisk
assessRisk
( risk)
assessRisk
assessRisk
36h. Scenarios to Interfaces (iii)
IAssessRisk
IAssessProfitAndRisk
Application
assessRisk
assessProfit
IAssessRisk
Applicant
IAssessRisk
1
n
IAssessProfitAndRisk
Borrower
1
0-1
BorrowingAccount
1
n
IAssessProfitAndRisk
IAssessProfitAndRisk
assessRisk
37i. Intra-Class Roles to Interfaces (i)
- Strategy design-in, from intra-class roles to
interfaces. - Identify roles that objects within a class can
play. - Establish an interface for each of those roles.
- Identify implementers.
38i. Intra-Class Roles to Interfaces (ii)
ITransferSource
Account
transferTo
ITransferSource
ITransferDestination
ITransferDestination
transferFrom
Name
Transfer from one account to another.
Account from
Account to
Constraints
transferFrom
transferTo
(amount, transferTo result)
transferFrom
transferFrom
(amount result)
transferTo
transferTo
39j. Plug-In Methods to Interfaces (i)
- Strategy design-in, from plug-in methods to
interfaces. - Look for useful functionality youd like to "plug
in. - Add a plug-point, using an interface.
- Identify implementers.
40j. Plug-In Methods to Interfaces (ii)
Term
IValidateTerm
1
validateTerm
validate
Name
Validate a term.
IValidateTerm Implementer
Term
Constraints
validateTerm
validate
( result)
validate
validate
( result)
validateTerm
validateTerm
public class Term extends Object private
IValidateTerm validater public int validate()
return validater.validateTerm()
public interface IValidateTerm public int
validateTerm()
413. Design with Threads
- A thread is a stream of program execution.
42Multiple Threads
this.mainThread new Thread (this) this.mainThre
ad.start()
43Why Threads
44Threads and Shared Values (a)
45Threads and Shared Values (b)
46Threads and Synchronized Methods (a)
Name
Reserve space.
FlightDescription
ScheduledFlight
Constraints
reserve
reserve
(passenger, date reservation)
reserve
reserve
SYNC
SYNC
(passenger reservation)
reserve
reserve
ENDSYNC
ENDSYNC
reserve
reserve
SYNC
SYNC
(passenger reservation)
reserve
reserve
ENDSYNC
ENDSYNC
public class ScheduledFlight extends Object
public synchronized Reservation reserve(Passenger
aPassenger, Date aDate) /code/
47Threads and Synchronized Methods (b)
- At the start of a syncd method, ð just one
thread may enter. - That thread can invoke non-syncs ð no waiting.
- That thread can invoke syncs in the same
object ð no waiting. - That thread can invoke syncs in other objects ð
potential waiting, potential for deadlock.
48Threads and Synchronized Methods (c)
.
49Thread Strategies (a)
- "Short Synchronized Methods" Strategy
- Keep synchronized methods short and to the point.
- "Thread Gatekeeper" Strategy
- Use a thread gatekeeper, an object that permits
just one thread at a time into a collection of
cross-messaging objects.
50Thread Strategies (b)
- "Four Thread Designs" Strategy
- Single
- Prioritized objects (hi-pri objects, low-pri
objects) - Prioritized methods (hi-pri methods low-pri
methods) - Combo
514. Design with Notification
52Observer-Observable (inheritance)
inheritance of a utility function--gack!
overly restrictive interface--gack!
Observable
addObserver
deleteObserver
Observer
deleteObservers
update
n
notifyObservers
java.util
SpecializedObservable
status
methodResultingInStateChg
getStatus
public interface Observer void update
(Observable observed Object argument)
53Observer-Observable (composition sketch)
54Observer-Observable (composition model)
ObservableComponent
MyObservable
MyObserver
myValue
n IObserver
1 IObservableComponent
IObservableComponent
IObservable
IMyInterface
IObserver
1 IMyInterface
IObserver
IObservable
IObservableComponent
IMyInterface
update
addIObserver
IObservable
getMyValue
deleteIObserver
notifyIObservers
setMyValue
deleteIObservers
public class ObservableComponent extends Object
implements IObservableComponent private
Vector myObservers /created by constructor/
public void notifyObservers() Vector
copyMyObservers (Vector) this.myObservers.clone(
) Enumeration myObserverList
this.copyMyObservers.elements() while
(myObserverList.hasMoreElements())
IObserver observer (IObserver)
myObserverList.nextElement()
observer.update()
55Threaded Observer-Observable (sketch)
56Threaded Observer-Observable (model)
Thread
ThreadedObservableComponent
start
1 Runnable
1
MyObservable
IObservableComponent
1 IObservableComponent
MyObserver
Runnable
myValue
n IObserver
IObservable
IMyInterface
IObserver
1 IMyInterface
Runnable
IObservableComponent
IObserver
IMyInterface
run
IObservable
update
getMyValue
notifyIObservers
setMyValue
public class ThreadedObservableComponent extends
Object implements IObservableComponent,Runnable
public void notifyObservers()
this.addToNotificationQueue(observers,
observable, changeCode) public void
run() do // get the next
observers-observable-changeCode triad
// and notify the observers while
this.removeFromNoticationQueue()
IObservable
addIObserver
deleteIObserver
deleteIObservers
57Event SourceEvent Listener (sketch)
58Event SourceEvent Listener (model)
EventObject
EventListener
java.util
ltnonegt
getSource
MyEventSource
MyEvent
MyEventListener
myData
EventListener
addMyEventListener
getMyData
n
change
removeMyEventListener
fireMyEvent
public class MyEventSource extends Object
private Vector myEventListeners /created by
constructor/ public void fireMyEvent()
MyEvent myEvent new MyEvent() /then
initialize it/ Vector copyMyEventListeners
(Vector) this.myEventListeners.clone()
Enumeration myEventListenerList
copyMyEventListeners.elements()
MyEventListener myEventListener
(MyEventListener) myEventListenerList.nextElement(
) myEventListener.change(myEvent)
59Property Change Source-Support-Listener (sketch)
60Property Change Source-Support-Listener (model)
PropertyChangeEvent
PropertyChangeSupport
PropertyChangeListener
source
EventListener
propertyName
n
propertyChange
addPropertyChangeListener
oldValue
removePropertyChangeListener
newValue
firePropertyChange
java.beans
better design define and use an
IPropertyChangeSupport interface
1
MyObject
addPropertyChangeListener
removePropertyChangeListener
setltpropertyNamegt
public class MyObject extends Object private
String name private PropertyChangeSupport
myPropertyChangeSupport public void
setName(String aName) this.name aName
myPropertyChangeSupport.firePropertyChange()
615. Build with Java
- Design it.
- Build it with the "Chia Pet Process J
- Class
- H ...
- Initialize and implement
- Access
- Print
- Equal
- Test
A "Chia Pet" is a small toy, marketed
in various parts of the globe and honorably
mentioned in the movie, Wayne's World. The
letters C,I,A,P,E,T represent the steps in this
process.
Acknowledgement Jill Nicola developed this
process. Nicola 97
62Design It.
IName
getName
Individual
setName
name
borrower
TestIndividual
IBorrow
IName
totalOutstandingBalance
1
0-1
-
IBorrow
main
equals
toString
buildTestObject
63Class
// Individual.java public class Individual
extends Object implements IName, IBorrow
private String name
//attribute private IBorrow
borrower
//object connection public String getName()
/code/ //methods public
void setName(String aName) /code/ public
double totalOutstandingBalance() /code/
// IBorrow.java public interface IBorrow
public double totalOutstandingBalance() //
IName.java public interface IName public
String getName() public void setName (String
aName)
64Initialize and Implement
// Individual.java (cont.) public
Individual(String aName) this.name
aName this.borrower null public
String getName() return this.name
public void setName(String aName)
this.name aName public double
totalOutstandingBalance() if
(this.borrower ! null) return
this.borrower.totalOutstandingBalance()
/delegates/ else return 0.0d
65Access
// Individual.java (cont.) public String
getName() return this.name public
void setName(String aName) this.name
aName
66Print
// Individual.java (cont.) public static int
MAXNAMELEN 100 public String toString()
StringBuffer aStringBuffer new
StringBuffer(MAXNAMELEN)
aStringBuffer.append(this.getName()) if
(this.borrower ! null)
aStringBuffer.append(" is an individual and a
borrower.") else
aStringBuffer.append(" is an individual, not a
borrower.") return aStringBuffer.toString()
67Equal
meaning does this other object in the same
classhave equal attribute values and object
connections?
// Individual.java (cont.) public boolean
equals(Object anObject) if ((anObject !
null) (anObject instanceof Individual))
Individual otherIndividual
(Individual)anObject return
this.name.equals(otherIndividual.name)
this.borrower.equals(otherIndividual.borrow
er) else return false
68Test
// Individual.java (cont.) public static
Individual buildTestObject() return new
Individual ("Fred Flinstone) //
TestIndividual.java import java.io. public
class TestIndividual public static void
main(String args) Individual
anIndividual Individual.buildTestObject()
for (int i 0 i lt 5 i) System.out.println()
System.out.println("This is a test.")
System.out.println(anIndividual.toString())
System.out.println("The end.")
BufferedReader in new BufferedReader(new
InputStreamReader(System.in)) // A
"stream" is a data-holding area with an
associated cursor. // An "input stream
reader" reads characters from a byte input
stream. // A "buffered reader" reads a
buffer of characters from a reader. try
String line in.readLine()
catch(Exception e) System.out.println("readLine
exception")
69Summary
- Purpose
- To gain insights into better design
- Agenda
- 1. Design with Composition, Rather than
Inheritance. - 2. Design with Interfaces.
- 3. Design with Threads.
- 4. Design with Notification.
- 5. Build with Java.
For more Java Design, see Coad97a
70For More...
- Newsletter
- Coad,"The Coad Letter." Free technical
newsletter. Subscribe at www.oi.com/newsletters.ht
m - Books and Workshop Notes
- Coad97a Coad and Mayfield, Java Design
Building Better Apps and Applets. Prentice Hall,
1997. - Coad97b Coad, North, Mayfield, Object Models
Strategies, Patterns, and Applications. Second
Edition. Prentice Hall, 1997. - Coad97c Coad, Peter, How to Build Better Object
Models. Workshop Notes. Object International,
1997. - Nicola97 Nicola, Jill, Java Programming A
Design-Centric Approach. Workshop Notes. Object
International, 1997.
71JAVA DESIGNBuilding Better Apps and Applets
- Peter Coad
- Object International, Inc.
- www.oi.com pc_at_oi.com
- 1-919-772-9350 fax -9389
- direct line -7734 direct fax -8916