Design Pattern: Decorator Pattern

I was perusing DZone last night/this morning and came across a nice blog entry by Gary Short talking about the Decorator Design Pattern.  While his original blog entry was great - it wasn't a pure decorator example - as one of his readers pointed out.  I think that it followed the pattern in spirit, though - if not in exact implementation.  As I've used the Decorator a few times in the past, I posted a quick example directly to his comments. 

Unfortunately, the comment formatting was hardly desirable.  It stripped out all spaces, breaking lines, etc.  So, here is the code in a much prettier format:

'// Start with the interface
Public Interface IMortgageBill

    Function Calculate() As Decimal

End Interface

'// Then create an abstract class, implementing the Interface.
Public MustInherit Class AMortgageBillDecorator
    Implements IMortgageBill

    Protected _bill As IMortgageBill

    Public Sub New(ByVal decoratedBill As IMortgageBill)
        _bill = decoratedBill
    End Sub

    Public MustOverride Function Calculate() _
            As Decimal Implements IMortgageBill.Calculate
End Class

'// Then you have a base class - something that you will want to
'// decorate.
Public Class RegularMortgageBill
    Implements IMortgageBill

    Public Function Calculate() As Decimal Implements IMortgageBill.Calculate
        Return New Decimal(5)
    End Function
End Class

'// Then you can create an overabundance of decorators - here's 
'// two.

'// The LatePaymentDecorator
Public Class LatePaymentDecorator
    Inherits AMortgageBillDecorator

    Public Sub New(ByVal decoratedBill As IMortgageBill)
        MyBase.New(decoratedBill)
    End Sub

    Public Overrides Function Calculate() As Decimal
        Return Me._bill.Calculate + New Decimal(5)
    End Function
End Class

'// And the California Tax Decorator
Public Class CaliforniaTaxDecorator
    Inherits AMortgageBillDecorator

    Public Sub New(ByVal decoratedBill As AMortgageBillDecorator)
        MyBase.New(decoratedBill)
    End Sub

    Public Overrides Function Calculate() As Decimal
        Return Me._bill.Calculate() + New Decimal(5)
    End Function
End Class
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

And here is the code to actually use these classes:

Module Main

    '// Then you simply write the code to instantiate these guys:
    Sub Main()
        Dim payment As IMortgageBill

        payment = New RegularMortgageBill()

        If True = True Then
            '// If user paid late last month.
            payment = New LatePaymentDecorator(payment)
        End If

        If True = True Then
            '// If user is in California
            payment = New CaliforniaTaxDecorator(payment)
        End If

        System.Console.WriteLine("Payment: " & _
                    payment.Calculate().ToString)
        System.Console.ReadLine()

    End Sub

End Module
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

As you can see above - this is the true power of the Decorator pattern...the ability to stack decorators on top of each other provides for an incredible extensibility mechanism. 

Technorati Tags: , ,
Published 05 July 07 09:15 by Greg

Comments

# Design Patterns #6 - The Decorator Pattern said on July 6, 2007 3:18 AM:

PingBack from http://www.garyshort.org/?p=652

Anonymous comments are disabled