Chapter 26 GoF Design Patterns. The Adapter Design Pattern.
-
Upload
jasmin-wilcox -
Category
Documents
-
view
249 -
download
0
Transcript of Chapter 26 GoF Design Patterns. The Adapter Design Pattern.
![Page 1: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/1.jpg)
Chapter 26
GoF Design Patterns
![Page 2: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/2.jpg)
The Adapter Design Pattern
TaxMasterAdapter
getTaxes( Sale ) : List of TaxLineItems
GoodAsGoldTaxProAdapter
getTaxes( Sale ) : List of TaxLineItems
«interface»ITaxCalculatorAdapter
getTaxes( Sale ) : List of TaxLineItems
Adapters use interfaces and polymorphism to add a level of indirection to varying APIs in other components.
SAPAccountingAdapter
postReceivable( CreditPayment )postSale( Sale )...
GreatNorthernAccountingAdapter
postReceivable( CreditPayment )postSale( Sale )...
«interface»IAccountingAdapter
postReceivable( CreditPayment )postSale( Sale )...
«interface»IInventoryAdapter
...
«interface»ICreditAuthorizationService
Adapter
requestApproval(CreditPayment,TerminalID, MerchantID)...
![Page 3: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/3.jpg)
Interaction Diagram for “Adapter”
:Register : SAPAccountingAdapter
postSale( sale )
makePayment
the Adapter adapts to interfaces in other components
SOAP over HTTP
xxx
...
«actor»: SAPSystem
![Page 4: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/4.jpg)
Sometimes we update domain models to reflect our more refined understanding of domain
Sale
dateTime…...
SalesLineItem
quantity
Contains
1..*
1
TaxLineItem
descriptionpercentageamount
Contains
1..*
1
...
...
...
...
![Page 5: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/5.jpg)
The Factory Pattern
ServicesFactory
accountingAdapter : IAccountingAdapterinventoryAdapter : IInventoryAdaptertaxCalculatorAdapter : ITaxCalculatorAdapter
getAccountingAdapter() : IAccountingAdaptergetInventoryAdapter() : IInventoryAdaptergetTaxCalculatorAdapter() : ITaxCalculatorAdapter...
note that the factory methods return objects typed to an interface rather than a class, so that the factory can return any implementation of the interface
if ( taxCalculatorAdapter == null ) { // a reflective or data-driven approach to finding the right class: read it from an // external property
String className = System.getProperty( "taxcalculator.class.name" ); taxCalculatorAdapter = (ITaxCalculatorAdapter) Class.forName( className ).newInstance();
} return taxCalculatorAdapter;
![Page 6: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/6.jpg)
The Factory Pattern
• Advantages:– Separate the responsibility of complex object creation
into cohesive helper objects– Hide potentially complex creation logic– Allow optimizations to enhance performance
• Object caching: Create objects beforehand and keep them in memory for quick use.
• Re-cycling: Pool of connection threads in a web-server.
• ServicesFactory:– Data-driven design: Class loaded dynamically (at run
time) based on system property.– Can create other adapter classes by changing
property value
![Page 7: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/7.jpg)
The Singleton Pattern
• Issues with the factory pattern:– Who creates the factory itself?– How do we get access to the
factory class from everywhere?
![Page 8: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/8.jpg)
Accessing the Singleton
:Register1
:ServicesFactory
aa = getAccountingAdapterinitialize
...
the ‘1’ indicates that visibility to this instance was achieved via the Singleton pattern
public class Register { public void initialize() { ... aa = ServicesFactory.getInstance().getAccountingAdapter();
... }}
![Page 9: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/9.jpg)
The Singleton Pattern: Implementation and Design Issues
• Lazy initialization:public static synchronized ServicesFactory getInstance() { if (instance == null) instance = new ServicesFactory(); return instance;}
• Eager initialization: ???
![Page 10: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/10.jpg)
The Singleton Pattern: Implementation and Design Issues
• Lazy initialization:public static synchronized ServicesFactory getInstance() { if (instance == null) instance = new ServicesFactory(); return instance;}
• Eager initialization:public class ServicesFactory { private static ServicesFactory instance = new ServicesFactory();
public static ServicesFactory getInstance() { return instance; } }
![Page 11: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/11.jpg)
Singleton Issues
• Lazy vs. eager initialization. Which one is better?– Laziness, of course!
• Creation work (possibly holding on to expensive resources) avoided if instance never created
• Why not make all the service methods static methods of the class itself?– Why do we need an instance of the factory
object and then call its instance methods?
![Page 12: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/12.jpg)
Singleton Issues
• Why not make all the service methods static methods of the class itself?– To permit subclassing: Static methods are not
polymorphic, don’t permit overriding.– Object-oriented remote communication
mechanisms (e.g. Java RMI) only work with instance methods
• Static methods are not remote-enabled.
– More flexibility: Maybe we’ll change our minds and won’t want a singleton any more.
![Page 13: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/13.jpg)
Design Patterns in Interaction Diagrams
:Register accountingAdapter: SAPAccountingAdapter
postSale( sale )
makePayment
SOAP over HTTP
xxx
:Register
1:ServicesFactory
accountingAdapter = getAccountingAdapter
:Store
createcreate
: SAPAccountingAdapter
: Paymentcreate(cashTendered)
«actor»: SAPSystem
create
![Page 14: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/14.jpg)
The Strategy Pattern
PercentDiscountPricingStrategy
percentage : float
getTotal( s:Sale ) : Money
AbsoluteDiscountOverThresholdPricingStrategy
discount : Moneythreshold : Money
getTotal( s:Sale ) : Money
«interface»ISalePricingStrategy
getTotal( Sale ) : Money
{ return s.getPreDiscountTotal() * percentage }
???PricingStrategy
...
...
{pdt := s.getPreDiscountTotal() if ( pdt < threshold ) return pdtelse return pdt - discount }
• Issue: Provide more complex pricing logic.– Pricing strategy varying over time– Example: Different kinds of sales.
![Page 15: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/15.jpg)
Interaction diagram for “Strategy”
:PercentDiscountPricingStrategy
s : Sale
st = getSubtotal
t = getTotal
lineItems[ i ] :SalesLineItem
t = getTotal( s )
pdt = getPreDiscountTotal
{ t = pdt * percentage }
note that the Sale s is passed to the Strategy so that it has parameter visibility to it for further collaboration
loop
Context object
![Page 16: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/16.jpg)
Context object has attribute visibility to its strategy
PercentDiscountPricingStrategy
percentage : float
getTotal( Sale ) : Money
AbsoluteDiscountOverThresholdPricingStrategy
discount : Moneythreshold : Money
getTotal( Sale ) : Money
«interface»ISalePricingStrategy
getTotal( Sale ) : Money
Sale
date...
getTotal()...
1
Sale needs attribute visibility to its Strategy
pricingStrategy
getTotal(){...return pricingStrategy.getTotal( this )
}
![Page 17: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/17.jpg)
Factory for Strategy Object
1PricingStrategyFactory
instance : PricingStrategyFactory
getInstance() : PricingStrategyFactory
getSalePricingStrategy() : ISalePricingStrategygetSeniorPricingStrategy() : ISalePricingStrategy...
{ String className = System.getProperty( "salepricingstrategy.class.name" ); strategy = (ISalePricingStrategy) Class.forName( className ).newInstance(); return strategy; }
![Page 18: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/18.jpg)
Factory Creates Strategy Object on Demand
:Sale
1:PricingStrategyFactory
ps =getSalePricingStrategy
:Register
makeNewSalecreate
create(percent) ps : PercentDiscountPricingStrategy
![Page 19: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/19.jpg)
The “Composite” Design Pattern
![Page 20: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/20.jpg)
The “Composite” Design Pattern
![Page 21: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/21.jpg)
The “Composite” Design Pattern
PercentageDiscountPricingStrategy
percentage : float
getTotal( Sale ) : Money
AbsoluteDiscountOverThresholdPricingStrategy
discount : Moneythreshold : Money
getTotal( Sale ) : Money
«interface»ISalePricingStrategy
getTotal( Sale ) : Money
{ return sale.getPreDiscountTotal() * percentage }
CompositePricingStrategy
add( ISalePricingStrategy )getTotal( Sale ) : Money
{lowestTotal = INTEGER.MAXfor each ISalePricingStrategy strat in pricingStrategies { total := strat.getTotal( sale ) lowestTotal = min( total, lowestTotal ) }return lowestTotal }
1..*
CompositeBestForCustomerPricingStrategy
getTotal( Sale ) : Money
CompositeBestForStorePricingStrategy
getTotal( Sale ) : Money
strategies
All composites maintain a list of contained strategies. Therefore, define a common superclass CompositePricingStrategy that defines this list (named strategies).
Sale
date...
getTotal()...
1
pricingStrategy
{...return pricingStrategy.getTotal( this )}
![Page 22: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/22.jpg)
public abstract class CompositePricingStrategy implements ISalePricingStrategy {
protected List strategies = new ArrayList();
public add (ISalePricingStrategy s) { strategies.add(s); }
public abstract Money getTotal( Sale sale );}
public class ComputeBestForCustomerPricingStrategy extends CompositePricingStrategy {
Money lowestTotal = new Money( Integer.MAX_VALUE );
for (Iterator i = strategies.iterator(); i.hasNext(); ) { ISalePricingStrategy strategy = (ISalePricingStrategy) i.next(); Money total = strategy.getTotal( sale ); lowestTotal = total.min( lowestTotal); } return lowestTotal;}
![Page 23: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/23.jpg)
Collaboration with a Composite
:CompositeBestForCustomerPricingStrategy
s : Sale
st = getSubtotal
t = getTotal
lineItems[ i ] :SalesLineItem
t = getTotal( s )
the Sale object treats a Composite Strategy that contains other strategies just like any other ISalePricingStrategy
x = getTotal( s )
strategies[ j ] :: ISalePricingStrategy
UML: ISalePricingStrategy is an interface, not a class; this is the way in UML 2 to indicate an object of an unknown class, but that implements this interface
{ t = min(set of all x) }
loop
loop
![Page 24: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/24.jpg)
Abstract Classes and Methods in the UML
CompositePricingStrategy
add( ISalePricingStrategy )getTotal( Sale ) : Money
CompositeBestForCustomerPricingStrategy
getTotal( Sale ) : Money
CompositeBestForStorePricingStrategy
getTotal( Sale ) : Money
UML notation: An abstract class is shown with an italicized name
abstract methods are also shown with italics
![Page 25: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/25.jpg)
Creating a Composite Strategy
:Sale
1:PricingStrategyFactory
ps =getSale
PricingStrategy
:Register
makeNewSale create
create ps :CompositeBestForCustomerPricingStrategy
create( percent ) s : PercentageDiscountPricingStrategy
add( s )
![Page 26: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/26.jpg)
Creating the Pricing Strategy for a Customer (Part 1)
![Page 27: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/27.jpg)
Creating the Pricing Strategy for a Customer (Part 2)
s :Sale
1:PricingStrategy
Factory
addCustomerPricingStrategy( s )
ps :CompositeBestForCustomerPricingStrategy
create( pct ) s : PercentageDiscountPricingStrategy
add( s )
by Expert
enterCustomerForDiscount( c : Customer )
c = getCustomer
by Factory and High Cohesion
by Expert ps = getPricingStrategy
pct = getCustomer
Percentage( c )
by High Cohesion
by Factory and Composite
Pass Aggregate Object as Parameter
sd Enter Customer For Discount
![Page 28: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/28.jpg)
Creating the Pricing Strategy for a Customer (Part 2)
s :Sale
1:PricingStrategy
Factory
addCustomerPricingStrategy( s )
ps :CompositeBestForCustomerPricingStrategy
create( pct ) s : PercentageDiscountPricingStrategy
add( s )
by Expert
enterCustomerForDiscount( c : Customer )
c = getCustomer
by Factory and High Cohesion
by Expert ps = getPricingStrategy
pct = getCustomer
Percentage( c )
by High Cohesion
by Factory and Composite
Pass Aggregate Object as Parameter
sd Enter Customer For Discount
WHY?
![Page 29: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/29.jpg)
The “Façade” Design Pattern
• Additional requirement in new iteration of POS: Pluggable business rules
• Example– New sale might be paid by gift certificate.
Only one item can be purchased by a gift certificate– If sale paid by gift certificate, invalidate all payments
with the type of “change due back to customer” different from gift certificate.
– Some sales might be charitable donations by the store. Limited to less than $250 each. Manager must be logged in as cashier for this transaction.
• One of the concerns: What happens to enterItem?
![Page 30: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/30.jpg)
enterItem and Low Impact of Change
• Suppose architect wants low impact of change in pluggable business rules.
• Suppose also that the architect is not sure how to implement the pluggable business rules.– Wants to experiment with different ways of implementing them.
• Solution: The “Façade” design pattern– Problem: Need a common, unified interface to a disparate set of
implementations or interfaces– Solution: Define a single point of contact to the subsystem
containing the implementations• This façade object has a unified interface• Internal implementation details hidden
– Example: The use-case controller objects in your project.
![Page 31: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/31.jpg)
The “Façade” Design Pattern
Domain
+ Sale + Register ...
POSRuleEngine
«interface»- IRule
...
- Rule1
...
- Rule2
...
...
package name may be shown in the tab
visibility of the package element (to outside the package) can be shown by preceding the element name with a visibility symbol
+ POSRuleEngineFacade
instance : RuleEngineFacade
getInstance() : RuleEngineFacade
isInvalid( SalesLineItem, Sale )isInvalid( Payment, Sale )...
*
![Page 32: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/32.jpg)
Façade code example
public class Sale {
public void makeLineItem( ProductDescription desc, int quantity) {SalesLineItem sli = new SalesLineItem( desc, quantity);
// call to the Façade. Notice Singleton pattern if (POSRuleEngineFacede.getInstance().isInvalid(sli,this) )
return; lineItems.add(sli); } //..}
![Page 33: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/33.jpg)
Observer/Publish-Subscribe/Delegation Event Model
• Another requirement: GUI window refreshes its display of the sales total when the total changes– Later: GUI updates display when other data
changes as well
• What’s wrong with the following?– When the Sale object changes its total, it
sends a message to a window, asking it to refresh the display?
![Page 34: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/34.jpg)
Publish-Subscribe Pattern
• What’s wrong with the following?– When the Sale object changes its total, it
sends a message to a window, asking it to refresh the display?
• Answer: The Model-View Separation principle discourages such solutions– Model objects (objects in the domain) should
not know of UI objects– If UI changes, model objects should not need
to change
![Page 35: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/35.jpg)
The Problem
Goal: When the total of the sale changes, refresh the display with the new value
Sale
total...
setTotal( newTotal )...
![Page 36: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/36.jpg)
«interface»PropertyListener
onPropertyEvent( source, name, value )
SaleFrame1
onPropertyEvent( source, name, value )
initialize( Sale sale )...
javax.swing.JFrame
...setTitle()setVisible()...
{ if ( name.equals("sale.total") ) saleTextField.setText( value.toString() );}
Sale
addPropertyListener( PropertyListener lis )publishPropertyEvent( name, value )
setTotal( Money newTotal )...
*propertyListeners
{ total = newTotal; publishPropertyEvent( "sale.total", total ); }
{ propertyListeners.add( lis );}
{ for each PropertyListener pl in propertyListeners pl.onPropertyEvent( this, name, value ); }
{ sale.addPropertyListener( this ) ... }
![Page 37: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/37.jpg)
Fig. 26.23
s : Salesf : SaleFrame1
initialize( s : Sale )
addPropertyListener( sf )
propertyListeners : List<PropertyListener>
add( sf )
![Page 38: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/38.jpg)
Fig. 26.24
s :Sale
setTotal( total )
onPropertyEvent( s, "sale.total", total )
publishPropertyEvent( "sale.total", total )
propertylisteners[ i ] : PropertyListener
loop
![Page 39: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/39.jpg)
Fig. 26.25
: SaleFrame1
onPropertyEvent( source, name, value )
saleTextField: JTextField
setText( value.toString() )
Since this is a polymorphic operation implemented by this class, show a new interaction diagram that starts with this polymorphic version
UML notation: Note this little expression within the parameter. This is legal and consise.
![Page 40: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/40.jpg)
Fig. 26.26
«interface»PropertyListener
onPropertyEvent( source, name, value )
SaleFrame1
onPropertyEvent( source, name, value )
initialize( Sale sale )...
javax.swing.JFrame
...setTitle()setVisible()...
Sale
addPropertyListener( PropertyListener lis )publishPropertyEvent( name, value )
setTotal( Money newTotal )...
*propertyListeners
publishes events to observers/listeners/subscribers
registers them when they ask to subscribe
listens for events observes events subscribes to notification of events
![Page 41: Chapter 26 GoF Design Patterns. The Adapter Design Pattern.](https://reader033.fdocuments.net/reader033/viewer/2022061614/56649eb05503460f94bb59c0/html5/thumbnails/41.jpg)
Fig. 26.27
«interface»AlarmListener
onAlarmEvent( source, time )
Beeper
onAlarmEvent( source, time )...
{ display notification dialog box }
AlarmClock
addAlarmnListener( AlarmListener lis )publishAlarmEvent( time )
setTime( newTime )...
*alarmListeners
{ time = newTime; if ( time == alarmTime ) publishAlarmEvent( time ); }
{ alarmListeners.add( lis );}
{ for each AlarmListener al in alarmListeners al.onAlarmEvent( this, time ); }
AlarmWindow
onAlarmEvent( source, time )...
javax.swing.JFrame
...setTitle()setVisible()...
ReliabilityWatchDog
onAlarmEvent( source, time )...
{ beep }
{ check that all required processes are executing normally }