Payroll Case Study - PowerPoint PPT Presentation

1 / 68
About This Presentation
Title:

Payroll Case Study

Description:

Some employees work by the hour. ... Upon receiving the Payday transaction, the system finds all those employees that ... Payday date Finding Abstractions ... – PowerPoint PPT presentation

Number of Views:430
Avg rating:3.0/5.0
Slides: 69
Provided by: cyndi8
Category:
Tags: case | payday | payroll | study

less

Transcript and Presenter's Notes

Title: Payroll Case Study


1
Section 3
  • Payroll Case Study

2
The Payroll System Initial Requirement
pay employees
correct amount (minus deductions)
Employee Database
Payroll System
on time
method specified
3
Payroll Initial Spec
  • Pay Type
  • Hourly. Some employees work by the hour. Paid
    hourly rate. Submit time cards. Paid overtime _at_
    1.5 times rate. Paid every Friday.
  • Salary. Some employees salaried. Paid last
    working day of month.
  • Commission. Some employees also paid commission
    based on sales. Submit sales amounts. Paid every
    Friday.
  • Commission rate, salary, hourly rate are part of
    employee record.
  • Pay Method.
  • Employees can choose for paychecks to be mailed,
    held for pickup, or directly deposited to bank
    account.
  • Deductions.
  • Some employees belong to the union. Employee
    record has field for weekly dues rate. Must be
    deducted from pay. Union may assess service
    charges from time to time. These are submitted
    by union on weekly basis and must be deducted
    from appropriate employees next pay amount.
  • Other requirements.
  • Payroll application will run once each working
    day and pay the appropriate employees on that
    day. The system will be told to what date the
    employees are to be paid, so it will calculate
    payments from the last time the employee was paid
    up to the specified date.

4
Chapter 18
  • Payroll Case Study

5
How to begin?
  • Obviously a database is involved. Should we
    generate a database schema and some queries?
  • Common but this generates an application for
    which the database is the central concern.
  • Databases are implementation details!
  • Considering the database should be deferred as
    long as possible.
  • Abstraction the amplification of the essential
    and the elimination of the irrelevant. The
    database is irrelevant at this stage it is
    merely a technique used for storing and accessing
    data, nothing more.

6
Analysis by Use Cases
  • Start by considering the behavior of the system.
  • Use case similar to a story, but elaborated with
    more detail
  • Stories for this iteration
  • Add a new employee
  • Delete an employee
  • Post a time card
  • Post a sales receipt
  • Post a union service charge
  • Change employee details (e.g., hourly rate, dues
    rate)
  • Run the payroll for today

7
Use Case 1 Add New Employee
  • A new employee is added by the receipt of an
    AddEmp transaction. This transaction contains
    the employees name, address, and assigned
    employee number. The transaction has 3 forms
  • AddEmp ltEmpIdgt ltnamegt ltaddressgt H
    lthourly-rategt
  • AddEmp ltEmpIdgt ltnamegt ltaddressgt S
    ltmonthly-salarygt
  • AddEmp ltEmpIdgt ltnamegt ltaddressgt C
    ltmonthly-salarygt ltcomm-rategt
  • The employee record is created with fields
    assigned appropriately.
  • Alternative 1
  • An error in the transaction structure.
  • If the transaction structure is inappropriate, it
    is printed out in an error message and no action
    is taken.

8
Thinking about the design
  • Use case 1 hints at an abstraction

Well look at the COMMAND pattern for this
abstract base class
AddHourly Employee Transaction
AddSalaried Employee Transaction
AddCommissioned Employee Transaction
SRP adhered to each responsibility in its own
class
Dont get sucked into the database yet!!
9
OK to think about objects
Employee
Hourly Employee
Salaried Employee
Commissioned Employee
Possible Employee class hierarchy
10
Use Case 2 Delete an Employee
  • Employees are deleted when a DelEmp transaction
    is received. The form of this transaction is as
    follows
  • DelEmp ltEmpIdgt
  • When this transaction is received, the
    appropriate employee record is deleted.
  • Alternative 1
  • Invalid or unknown EmpID
  • If the ltEmpIDgt field is not structured correctly,
    or it does not refer to a valid employee record,
    then the transaction is printed with an error
    message and no other action is taken.

No design insights from this use case, so lets
move on
11
Use Case 3 Post Time Card
  • On receiving a TimeCard transaction, the system
    will create a time-card record and associate it
    with the appropriate employee record.
  • TimeCard ltEmpIdgt ltdategt lthoursgt
  • Alternative 1
  • The selected employee is not hourly
  • The system will print an appropriate error
    message and take no further action
  • Alternative 2
  • An error in the transaction structure
  • The system will print an appropriate error
    message and take no further action

12
Design insights
  • Some transactions apply only to certain kinds of
    employees strengthen case for different
    classes.
  • Indicates association between time cards and
    hourly employees.

Hourly Employee
0..
TimeCard
remember aggregation?
13
Use Case 4 Posting a Sales Receipt
  • Upon receiving the SalesReceipt transaction, the
    system will create a new sales-receipt record and
    associate it with the appropriate commissioned
    employee.
  • SalesReceipt ltEmpIdgt ltdategt ltamountgt
  • Alternative 1
  • The selected employee is not commissioned.
  • The system will print an appropriate error
    message and take no further action.
  • Alternative 2
  • An error in the transaction structure.
  • The system will print an appropriate error
    message and take no further action.

14
Design insights
  • This is very similar to use case 3. It implies
    the following structure

Commissioned Employee
0..
Sales Receipt
15
Use Case 5 Post Union Service Charge
  • Upon receiving this transaction, the system will
    create a service-charge record and associate it
    with the appropriate union member.
  • ServiceCharge ltmemberIDgt ltamountgt
  • Alternative 1
  • Poorly formed transaction
  • If the transaction is not well formed or if the
    ltmemberIDgt does not refer to an existing union
    member, then the transaction is printed with an
    appropriate error message.

16
Design Insights
  • Union members are not accessed through employee
    IDs. The union maintains its own numbering
    scheme. The system must be able to associate
    union members and employees. Could be done
    various ways, so postpone decision until later.
    Just show association for now.

Example of how this differs from waterfall
0..
UnionMember
ServiceCharge
17
Use Case 6 Change Employee Details
  • Upon receiving this transaction the system will
    alter one of the details of the appropriate
    employee record. Several possible variations
  • ChgEmp ltEmpIDgt Name ltnamegt
  • ChgEmp ltEmpIDgt Address ltaddressgt
  • ChgEmp ltEmpIDgt Hourly lthourlyRategt // Change to
    hourly
  • ChgEmp ltEmpIDgt Salaried ltsalarygt // Change to
    salary
  • ChgEmp ltEmpIDgt Commissioned ltsalarygt ltrategt
  • ChgEmp ltEmpIDgt Hold
  • ChgEmp ltEmpIDgt Direct ltbankgt ltaccountgt
  • ChgEmp ltEmpIDgt Mail ltaddressgt
  • ChgEmp ltEmpIDgt Member ltmemberIDgt Dues ltrategt
  • ChgEmp ltEmpIDgt NoMember
  • Alternative 1
  • An error in the transaction structure.
  • If the transaction structure is inappropriate, or
    ltEmpIDgt does not refer to a real employee, or
    ltmemberIDgt already refers to a member, then print
    a suitable error and take no further action

18
Design insights
  • Use case has shown all aspects of employee that
    are changeable.
  • Note that employees can change from hourly to
    salaried and vice versa. Initial class design
    may not be appropriate. Use STRATEGY pattern
    instead (see class diagram next slide)
  • Use the NULL OBJECT pattern for union membership.

19
Updated class design
ltltinterfacegtgt Payment Method
Employee
ltltinterfacegtgt Affiliation
Payment Classification
NoAffiliation
HoldMethod
0..
ServiceCharge
Commissioned Classification - CommissionRate -
Salary
0..
0..
TimeCard
SalesReceipt
20
Use Case 7 Run Payroll for Today
  • Upon receiving the Payday transaction, the system
    finds all those employees that should be paid on
    the specified date. The system then determines
    how much they are owed and pays them according to
    their selected payment method.
  • Payday ltdategt

21
Finding Abstractions
  • Must hunt for abstractions, because often not
    stated or even alluded to by application
    requirements.
  • Example
  • Some employees work by the hour
  • Some employees are paid a flat salary
  • Some employees are paid a commission
  • Generalization All employees are paid, but they
    are paid by different schemes.
  • Abstraction All employees are paid. Lead to
    PaymentClassification.

22
Another abstraction
  • Scheduling the payroll
  • They are paid every Friday
  • They are paid on last working day of month
  • They are paid every other Friday
  • Generality All employees are paid according to
    some schedule.
  • Abstraction schedule.
  • Use cases link schedule to payment
    classification. BUT, it seems possible that this
    could change (e.g., employees in different
    departments might be paid on different days).
    Also, if linked then a change in payment
    classification would require testing the schedule
    as well.
  • Schedule abstraction not included in original
    design

23
Chapter 13
  • COMMAND and
  • ACTIVE OBJECT

24
COMMAND simple elegant
public interface Command public void do()
ltltinterfacegtgt Command do()
Elevates the role of a function to the level of a
class. Blasphemy! But interesting designs can
unfold
25
Simple Commands
do()
ltltinterfacegtgt Command do()
do()
RelayOn Command
MotorOn Command
ClutchOn Command
init ClutchOnCommand MotorOnCommand
RelayOff Command
MotorOff Command
ClutchOff Command
Embedded real-time software for a photocopier.
Pass Command() objects around system and call
do() without knowing which type of Command they
represent. Example sensor needs to engage
clutch at point in paper path. Bind appropriate
ClutchOnCommand to object, Sensor detects event,
calls do(). Complexity of determining which
relays to connect to which sensors is now handled
by an initialization function.
26
Transactions a type of do()
  • Maintain database of employees. Number of
    operations that users can apply (add, delete,
    modify).
  • Command object collects unvalidated data,
    implements validation methods, executes
    transactions.

ltltinterfacegtgt Transaction validate() execute()
Employee - name - address
ltltinterfacegtgt PayClassification CalculatePay()
AddEmployee Transaction - name - address
validate() execute()
ltltinterfacegtgt Pay Classification CalculatePay()
Salaried Classification - monthlyPay
Hourly Classification - hourlyRate
Commissioned Classification - basePay -
commissionRate
0..
0..
SalesReceipt - date - amount
TimeCard - date - amount
27
Command Benefits
  • Physical and Temporal Decoupling
  • Decouple code that procures data from user
    (probably a dialog in some GUI) from code that
    validates and from business objects. If coupled,
    validation code couldnt be used other places.
    Code that manipulates database should also be
    separate.
  • Temporal decoupling. Transaction data can be
    collected and processed later. For example,
    maybe changes to database should only occur in
    the evening.
  • Undo
  • Easy to add an undo() method to the COMMAND
    pattern. Can reverse the effects of a do().

28
ACTIVE OBJECT
  • Old technique for implementing multiple threads
    of control.
  • Not covered threads covered in OS and PL

29
Chapter 14
  • TEMPLATE METHOD
  • STRATEGY
  • Inheritance vs. Delegation

30
Inheritance
  • Brave new world in early 90s
  • Could program by difference find class that did
    something almost useful to us, create subclass
    and change only what didnt work in new domain
  • BUT, easy to overuse inheritance
  • New advice Favor object composition over class
    inheritance
  • Need to carefully consider, use inheritance,
    composition and delegation appropriately

31
TEMPLATE METHOD - inheritance
  • Common main-loop structure

Initialize() while (!done()) // main loop
Idle() // do something useful Cleanup()
Use the pattern to create abstract base classes
that can work on various types of objects.
32
Example Bubble Sorter
  • First, we have a sort that knows how to work with
    integers

public class BubbleSorter static int
operations 0 public static int sort(int
array) operations 0 if
(array.length lt 1) return operations
for (int nextToLast array.length-2
nextToLast gt 0 nextToLast--) for (int
index 0 index lt nextToLast
index) compareAndSwap(array, index)
return operations
private static void swap (int array, int
index) int temp arrayindex
arrayindex arrayindex1 arrayindex1
temp private static void compareAndSwap
(int array, int index) if
(arrayindexgt arrayindex1) swap(array,
index) operations
33
Bubble Sorter, continued
  • Can create abstract class instead

public abstract class BubbleSorter private
int operations 0 protected int length 0
protected int doSort() operations 0
if (length lt 1) return operations
for (int nextToLast length-2 nextToLast gt
0 nextToLast--) for (int index 0
index lt nextToLast index)
if (outOfOrder(index)) swap(index)
operations return operations

protected abstract void swap(int
index) protected abstract boolean outOfOrder
(int index)
BubbleSorter abstract outOfOrder swap
DoubleBubble Sorter
IntBubble Sorter
34
Bubble Sorter, continued
  • Implement methods for Int and Double

public class DoubleBubbleSorter extends
BubbleSorter private double array null
public int sort(double theArray) array
theArray length array.length return
doSort() protected void swap(int index)
double temp arrayindex arrayindex
arrayindex1 arrayindex1 temp
protected boolean outOfOrder (int idx)
return (arrayidxgt arrayidx1)
public class IntBubbleSorter extends
BubbleSorter private int array null
public int sort(int theArray) array
theArray length array.length return
doSort() protected void swap(int index)
int temp arrayindex arrayindex
arrayindex1 arrayindex1 temp
protected boolean outOfOrder (int idx)
return (arrayidxgt arrayidx1)
35
STRATEGY pattern
  • Another way to solve the problem of inverting the
    dependencies
  • Instead of putting generic application algorithm
    in an abstract class, place it in a concrete
    class named ApplicationRunner
  • Abstract methods that must be called are defined
    in the Application interface
  • ftocStrategy is derived from this interface. An
    object of this class can be passed to
    ApplicationRunner

ftoc fahrenheit to celcius
ltltinterfacegtgt Application init idle
cleanup done boolean
concrete class
ftocStrategy
concrete class
36
Strategy code
public class ApplicationRunner private
Application itsApplication null public
ApplicationRunner(Application app)
itsApplication app public void run()
itsApplication.init() while
(!itsApplication.done()) itsApplication.idle
() itsApplication.cleanup()
can pass in ftocStrategy, etc.
public interface Application public void
init() public void idle() public void
cleanup() public boolean done()
calls methods from interface
37
Strategy code, continued
import java.io. public class ftocStrategy
implements Application private
InputStreamReader isr private BufferedReader
br private boolean isDone false public
static void main(String args) throws Exception
(new ApplicationRunner(new
ftocStrategy())).run() public void
init() isr new InputStreamReader(System.
in) br new BufferedReader(isr) //
More code in textbook
38
Strategy pros and cons
  • Strategy involves more classes
  • Delegation pointer in ApplicationRunner incurs
    some overhead
  • BUT
  • Easy to reuse ApplicationRunner by passing in
    different implementations of Application

39
Another example sorting again
public class BubbleSorter private int
operations 0 private int length 0
private SortHandle itsSortHandle null public
BubbleSorter(SortHandle handle)
itsSortHandle handle public int
sort(Object array) itsSortHandle.setArray(ar
ray) length itsSortHandle.length()
operations 0 if (length lt 1) return
operations for (int nextToLast length-2
nextToLast gt 0 nextToLast--)
for (int index 0 index lt
nextToLast index) if
(itsSortHandle.outOfOrder(index))
itsSortHandle.swap(index) operations
return operations
public interface SortHandle public void
swap(int index) public boolean outOfOrder(int
index) public int length() public void
setArray(Object array)
40
Sorting continued
public class IntSortHandle implements
SortHandle private int array null
public void swap(int index) int temp
arrayindex arrayindex arrayindex1
arrayindex1 temp public void
setArray(Object array) this.array
(int)array public int length()
return array.length public boolean
outOfOrder(int index) return (arrayindex
gt arrayindex1)
  • Notice
  • IntSortHandle knows nothing of BubbleSorter
  • IntSortHandle could therefore be used with other
    sorts e.g., QuickBubbleSorter that stops when
    the array is in order (code in text)
  • Strategy allows the details to be reused
    independently of the high-level algorithm!

More comparison sorts covered in CSCI406
41
Chapter 15
  • FAÇADE and
  • MEDIATOR

42
Policy patterns
  • Both Façade and Mediator impose some kind of
    policy on another group of objects
  • Façade imposes policy from above
  • Mediator imposes policy from below
  • Façade is visible and constraining
  • Mediator is invisible and enabling

43
Facade
  • Used to provide a simple, specific interface for
    a group of objects that has a complex, general
    interface

Product-specific sql interface complex but
shields users from knowing sql details
public class DB private static Connection
con public static void init() throws Exception
public static void store(ProductData pd)
throws Exception // Products private static
PreparedStatement buildProductInsertionStatement
ProductData pd) throws SQLException
public static ProductData getProductData(String
sku) throws Exception private static
PreparedStatement buildProductQueryStatement(Strin
g sku) private static ProductData
extractProductDataFromResultSet(ResultSet rs)
public static void store(ItemData id) throws
Exception // Items private static
PreparedStatement buildItemInsersionStatement(Item
Data id) public static ItemData
getItemsForOrder(int orderId) throws Exception
private static PreparedStatement
buildItemsForOrderQueryStatement (int
orderId) throws SQLException private static
ItemData extractItemDataFromResultSet(ResultSet
rs) public static OrderData
newOrder(String customerId) throws Exception
private static int getMaxOrderId() throws
SQLException // Orders public static OrderData
getOrderData(int orderId) throws SQLException
private static void executeStatement(PreparedState
ment s) public static void close() throws
Exception public static void clear() throws
Exception
44
DB Facade
DB store(ProductData) getProductData(sku)
deleteProductData(sku)
Application
ProductData
java.sql
Connection
Statement
DriverManager
ResultSet
Prepared Statement
SQLException
All database calls must go through DB. Direct
calls to java.sql violate convention. Policy is
visible application sees interface it provides.
Valid operations are all provided. Simplifies
application programmers dont all need to learn
sql interface, just use DB.
45
Mediator
  • Imposes policy in hidden, constrained way.
    QuickEntryMediator selects the first entry in a
    list that matches the current prefix in a
    JTextField.

State
JTextField
JList
CO
ALABAMA ALASKA ARIZONA ARKANSAS CALIFORNIA
COLORADO CONNECTICUT DELAWARE
ltltanonymousgtgt Document Listener
QuickEnty Mediator
Hidden Users of JList and JTextField have no
idea that this Mediator exists.
46
Mediator QuickEntry Example
State
List of states
public class QuickEntryMediator public
QuickEntryMediator(JTextField t, JList l)
itsTextField t itsList l
itsTextField.getDocument().addDocumentListener(
new DocumentListener() public void
changedUpdate(DocumentEvent e)
textFieldChanged() public
void insertUpdate(DocumentEvent e)
textFieldChanged() public
void removeUpdate(DocumentEvent e)
textFieldChanged() // new
DocumentListener ) // addDocumentListener
// QuickEntryMediator()
responds to JTextField events, shown
on next slide
47
Mediator QuickEntry continued
private void textFieldChanged() String
prefix itsTextField.getText() if
(prefix.length() 0) // clear selection if
user clears field itsList.clearSelection()
return ListModel m
itsList.getModel() // finds first item that
matches boolean found false //
text typed so far for (int i 0 found
false i lt m.getSize() i) Object o
m.getElementAt(i) String s
o.toString() if (s.startsWith(prefix))
itsList.setSelectedValue(o, true)
found true // found is true if any items in
list match prefix if (!found)
// clear if nothing matches text entry
itsList.clearSelection() //
textFieldChanged private JTextField
itsTextField private JList itsList // class
QuickEntryMediator
48
Chapter 16
  • SINGLETON and
  • MONOSTATE

49
Sometimes you only need one
  • Normally there is a one-to-many relationship
    between classes and objects
  • Some classes should only have one instance
  • factories
  • managers (e.g., print, other resources)
  • root of application
  • If more than one, logic errors may occur
  • May be able to just create one when application
    starts and be done with it
  • Sometimes it is important to enforce singularity
  • Two patterns to do that singleton monostate

application root
50
SINGLETON pattern
  • Simple to implement
  • Access through public method, e.g., Instance
  • Instance always returns same object
  • No public constructors, so cant create a second
    object of same type

public class Singleton private static Singleton
theInstance null private Singleton()
public static Singleton Instance() if
(theInstance null) theInstance new
Singleton() return theInstance
51
Testing the SINGLETON
public void testCreateSingleton() Singleton s
Singleton.Instance() Singleton s2
Singleton.Instance() assertSame(s,
s2) public void testNoPublicConstructors()
throws Exception Class singleton
Class.forName("Singleton") Constructor
constructors singleton.getConstructors() asser
tEquals("Singleton has public constructors.",
0, constructors.length)
52
Pros and Cons
  • Benefits of SINGLETON
  • Cross platform. Can extend to work across many
    JVMs and computers.
  • Applicable to any class. Just make constructors
    private and add static functions and variable.
  • Can derive a singleton from some other class.
    Given a class, can create a subclass that is a
    SINGLETON
  • Lazy evaluation. If SINGLETON is never used, it
    is never created
  • Costs of SINGLETON
  • Destruction undefined. If NULL out theInstance,
    other modules may still hold reference.
  • Not inherited. Class derived from SINGLETON is
    not a SINGLETON. Would need to add function to
    subclass.
  • Efficiency. Each call to Instance invokes an if
    statement, most often useless.
  • Nontransparent. Users of SINGLETON must know
    they are using SINGLETON because they must invoke
    Instance method.

So??
important?
53
SINGLETON Example
No IF statement, using Java initialization
  • private static UserDatabase theInstance
  • new UserDatabaseSource()
  • public static UserDatabase instance()
  • return theInstance
  • private UserDatabaseSource()
  • public User readUser(String userName)
  • // Some Implementation
  • return null // just to make it compile.
  • public void writeUser(User user)
  • // Some Implementation

Common usage, ensures all database access via
single instance of Façade.
54
Two possible approaches
  • MONOSTATE enforces the behavior of singularity
  • SINGLETON enforces the structure

55
MONOSTATE
  • Have multiple instances of Monostate, all act as
    one

import junit.framework. public class
TestMonostate extends TestCase public
TestMonostate(String name)
super(name) public void
testInstance() Monostate m new
Monostate() for (int x 0 xlt10 x)
m.setX(x) assertEquals(x, m.getX())

Two instances of Monostate behave as though they
were one
public void testInstancesBehaveAsOne()
Monostate m1 new Monostate()
Monostate m2 new Monostate() for (int
x 0 xlt10 x) m1.setX(x) assertEquals(x,
m2.getX())
56
MONOSTATE continued
  • How can that be?
  • Objects share same variables because they are
    static
  • BUT, none of the methods are static so they are
    accessed via actual instances of class objects

public class Monostate private static int
itsX 0 public Monostate() public
void setX(int x) itsX x
public int getX() return itsX
not static
57
Monostate Turnstile Example
  • Turnstile begins in locked state. Returns to
    locked state after people pass.
  • If coin is deposited, transition to Unlocked
    state, unlock gate, reset alarm, deposit coins in
    its bin
  • Abnormal condition 1 user deposits two coins
    before passing through. Coins are refunded, gate
    remains unlocked.
  • Abnormal condition 2 user passes through without
    paying. Alarm sounds, gate locked.

Turnstile finite state machine
Coin / Unlock, AlarmOff, Deposit
Pass / Alarm
Locked
Coin / Refund
Pass / Lock
58
Turnstile Code
public class Turnstyle private static boolean
isLocked private static boolean
isAlarming private static int
itsCoins private static int itsRefunds protect
ed final static Turnstyle LOCKED new
Locked() protected final static Turnstyle
UNLOCKED new Unlocked() protected static
Turnstyle itsState LOCKED public void
reset() lock(true) alarm(false) itsCoins
0 itsRefunds 0 itsState LOCKED
59
Turnstile code, continued
class Locked extends Turnstyle public void
coin() itsState UNLOCKED lock(false)
alarm(false) deposit() public
void pass() alarm(true)
class Unlocked extends Turnstyle public
void coin() refund() public void
pass() lock(true) itsState LOCKED

The event functions (coin and pass) are delegated
to two derivatives of Turnstyle (Locked and
Unlocked) that represent the states of the
finite-state machine. Derivatives are
automatically MONOSTATE. Since these are all
MONOSTATE, Locked and Unlocked are not really
separate objects, so no violation of OO
principles. NOTE Controlling more than one
turnstile would require significant refactoring.
60
Turnstile code, continued
  • See rest of code JUnit tests in textbook

61
Benefits of MONOSTATE
  • Transparency. Users do not need to know that
    object is MONOSTATE, because usage is same as for
    a regular object
  • Derivability. Derivatives of MONOSTATE are
    MONOSTATE they share the same variables
  • Polymorphism. Since methods are not static, they
    can be overridden. Different behavior, same set
    of static variables.
  • Well-defined creation and destruction. Static
    variables in MONOSTATE have well-defined creation
    and destruction times.

62
Costs of MONOSTATE
  • No conversion. Normal class cannot be converted
    to MONOSTATE through derivation.
  • Efficiency. May have many creations and
    destructions because MONOSTATE is a real object.
    These are costly operations.
  • Presence. Variables of MONOSTATE take up space,
    even if MONOSTATE never used.
  • Platform local. You cant make a MONOSTATE work
    across several JVM instances or across several
    platforms.

63
Which option to use?
  • SINGLETON is best when you have an existing class
    that you want to constrain through derivation,
    and you dont mind requiring users to call
    instance()
  • MONOSTATE is best when you want singular nature
    of class to be transparent or when you want to
    employ polymorphic derivatives

64
Chapter 17
  • NULL OBJECT

65
Common null code technique
  • Rely on short-circuit evaluation
  • Error-prone (may forget)
  • Try/catch can be even worse

Employee e DB.getEmployee(Bob) if (e ! null
e.isTimeToPay(today)) e.pay()
66
An alternative NULL OBJECT
  • Employee interface has two implementations
  • Normal implementation works as usual
  • NULL implementation methods do nothing

ltltinterfacegtgt Employee
DB
ltltcreatesgtgt
NullEmployee
Employee Implementation
ltltcreatesgtgt
NullEmployee is returned if Bob object doesnt
exist isTimeToPay will return false
Employee e DB.getEmployee(Bob) if
(e.isTimeToPay(today)) e.pay()
67
NULL Object Code
public class DB public static Employee
getEmployee(String name) return
Employee.NULL
public interface Employee public boolean
isTimeToPay(Date payDate) public void pay()
// NULL EMPLOYEE METHODS public static final
Employee NULL new Employee() public
boolean isTimeToPay(Date payDate) return
false public void pay()

Anonymous inner class ensures single instance
68
NULL Object Code continued
public void testNull() throws Exception
Employee e DB.getEmployee("Bob") if
(e.isTimeToPay(new Date())) fail()
assertEquals(Employee.NULL, e)
Write a Comment
User Comments (0)
About PowerShow.com