Applying the Decorator Pattern to the Case Study

In the case study, the SalesTicket is the ConcreteComponent. The concrete decorators are the headers and footers. Figure 15-5 shows the application of the Decorator pattern to the case study.

Figure 15-5. Setting up headers and footers to look like a report.


Figure 15-6 shows the application of Decorator to one header and one footer.

Figure 15-6. An example Decorator object diagram.


Each Decorator object wraps its new function around its trailing object. Each Decorator performs its added function either before its decorated function (for headers) or after it (for footers). The easiest way to see how it works is to look at code for a specific example and walk through it. See Example 15-1.

Example 15-1. Java Code Fragment: Decorator
class SalesTicket extends Component {
  public void prtTicket () {
    // sales ticket printing code here
  }
}
abstract class Decorator extends Component {
  private Component myComp;
  public Decorator (Component myC) {
    myComp= myC;
  }
  public void prtTicket () {
    if (myComp != null) myComp.prtTicket();
} }
class Header1 extends Decorator {
  public Header1 (Component myC) { super( myC); }
  public void prtTicket () {
    // place printing header 1 code here
    super.prtTicket();
} }
class Header2 extends Decorator {
  public Header2 (Component myC) { super( myC); }
  public void prtTicket () {
    // place printing header 2 code here
    super.prtTicket();
} }
class Footer1 extends Decorator {
  public Footer1 (Component myC) { super( myC); }
  public void prtTicket () {
    super.prtTicket();
    // place printing footer 1 code here
} }
class Footer2 extends Decorator {
  public Footer2 (Component myC) { super( myC); }
  public void prtTicket () {
    super.prtTicket();
    // place printing footer 2 code here
} }

class SalesOrder {
  void prtTicket () {
    Component myST;
    // Get chain of Decorators and SalesTicket built by
    // another object that knows the rules to use.
    // This may be done in constructor instead of
    // each time this is called.
    myST= Configuration.getSalesTicket()

    // Print Ticket with headers and footers as needed
    myST.prtTicket();
  }
}

If I want the sales ticket to look like:

HEADER 1

SALES TICKET

FOOTER 1

Then Configuration.getSalesTicket returns

return( new Header1( new Footer1( new SalesTicket()));

This creates a Header1 object trailed by a Footer1 object trailed by a SalesTicket object.

If I want the sales ticket to look like:

HEADER 1

HEADER 2

SALES TICKET

FOOTER 1

Then Configuration.getSalesTicket returns

return( new Header1( new Header2 (new Footer1(
                     new SalesTicket())));

This creates a Header1 object trailed by a Header2 object trailed by a Footer1 object trailed by a SalesTicket object.

The Decorator pattern helps to decompose the problem into two parts:

  • How to implement the objects that give the new functionality

  • How to organize the objects for each special case

This allows me to separate implementing the Decorators from the object that determines how they are used. This increases cohesion because each of the Decorators is only concerned with the function it adds—not in how it is added to the chain.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.252.81