For the Tax Office example given the Composite pattern may be better, see below.
Note:
1. In the example below the tax logic is in with the main classes, if you want to seperate the tax logic from the main logic you can pass the tax calculation to a referenced object or package private class with a static method.
2. I have used my own pet
Pattern
Enforcing
Compiler (
http://pec.dev.java.net) because it: enforces the Composite pattern, documents the roles of classes (Component, Leaf, or Composite), and as a blatent plug of my work :)
3. To use a conventional Java Compiler delete the import, references to Component, Leaf, and Composite, and write the body of TaxableComposite.extortCash.
class Tax {
double total; // A wrapper for a double so that you can pass a double by reference
}
import pec.compile.composite.*; // Import Composit pattern into PEC
interface Taxable extends Component {
void extortCash( Tax tax );
}
class TaxablePerson implements Taxable, Leaf {
public void extortCash( Tax tax ) {
tax.total += 2.718;
}
}
class TaxableCompany implements Taxable, Leaf {
public void extortCash( Tax tax ) {
tax.total += 3.142;
}
}
class TaxableComposite implements Taxable, Composite {
private final Taxable[] taxables;
TaxableComposite( final Taxable[] taxables ) {
this.taxables = taxables;
}
public void extortCash( Tax tax ) {
throw new AssertionError(); // Body written by PEC! - it steps over array calling extortCash
}
}
// Test useage:
public class TaxOffice {
public static void main( final String[] notUsed ) {
final TaxablePerson person = new TaxablePerson();
final Tax personTax = new Tax();
person.extortCash( personTax );
System.out.println( "Person's Tax = " + personTax.total );
final TaxableCompany company = new TaxableCompany();
final Tax companyTax = new Tax();
company.extortCash( companyTax );
System.out.println( "Company's Tax = " + companyTax.total );
final TaxableComposite all = new TaxableComposite(
new Taxable[] { person, company } );
final Tax totalTax = new Tax();
all.extortCash( totalTax );
System.out.println( "Total Tax = " + totalTax.total );
}
}
Which is arguably simpler than using a strategy. Note Composite and Strategy are similar in that they both rely on a base class.