Showing posts with label Structural design pattern. Show all posts
Showing posts with label Structural design pattern. Show all posts
Sunday, 4 November 2012

The decorator design pattern

The decorator pattern allows behaviour to be added to an existing object at runtime. This is achieved by wrapping the object (the component) in another class (the decorator).

Like the delegation pattern, the decorator pattern is similar to inheritance as it extends the functionality of a particular class. The primary difference between decorator and delegation is that the decorator pattern is more flexible, allowing multiple decorators to point to a single component at one time.

Reducing the complexity of an inheritance tree is one of the benefits to this pattern, imagine for example an application that prints a photo with an optional filter, an optional border and an optional rotation. This can be achieved in the following ways:

  • A single class with a lot of code; Photo
  • A class for each combination of options; Photo, BorderPhoto, FilterPhoto, RotatePhoto, BorderFilterPhoto, FilterRotatePhoto, BorderRotatePhoto, BorderFilterRotatePhoto
  • A class with optional decorators; Photo, PhotoFilterDecorator, PhotoBorderDecorator, PhotoRotateDecorator

The decorator pattern is of great use when implementing the open/closed principle, as described below:

software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification

Object-Oriented Software Construction, Bertrand Meyer

So once an application has been built, it should only be extended, not modified. It is particularly useful in a production environment as it reduces the amount of regression testing required. The decorator pattern is great here as it's simple to extend existing components in a completely modular way.

Benefits

  • Add behaviour to a component dynamically at runtime
  • Attach multiple decorators to a single component at one time
  • Completely modular, we don't need to touch the existing component
  • Can reduce the amount subclasses of a class

Drawbacks

  • Overuse of the decorator pattern can lead to very abstract and complex code
Saturday, 21 July 2012

The delegation design pattern

The delegation design pattern allows an object to delegate one or more tasks to a helper object. Two classes are used to achieve this; the delegate and delegator, both which realise a common interface. A method (or methods) on the interface represent the functionality to be delegated. A call to the delegator calls the matching function on the delegate.

While this seemingly just abstracts away some of the functionality into another class, the real power of this pattern comes when there are multiple delegates. The delegator typically has a method for each delegate that will convert the delegator to use that delegate.

It is useful for understanding to compare the delegation pattern to inheritance. Both are powerful reuse techniques with a few of key differences; inheritance is directly supported by today's object-oriented programming languages and enables the use of polymorphism, whereas the delegation pattern allows the delegate to be changed at run-time.

Benefits

  • Clearly separates the different sets of functionality
  • Run-time flexibility

Drawbacks

  • Not as trivial as implementing inheritance
Friday, 27 April 2012

The lazy loading design pattern

The lazy-loading design pattern provides a means to defer the creation of an object by loading it at the point it is needed. This has both benefits and drawbacks.

Benefits

  • Save memory by only loading what is needed when it's needed.
  • Reduce initial load time by deferring execution.

Drawbacks

  • There may be a delay the first time you need the object you're lazy-loading.

Lazy-loading is often a key feature of ORMs, which perform database queries only when the data is required in order to reduce the amount of data retrieved. This can lead to some issues with certain data not being present, you can usually get around this by explicitly specifying what you need. It is important to understand why this can occur when working with an ORM to prevent obscure bugs.