DECORATOR PATTERNFLYWEIGHT PATTERN
Matt Klein
Decorator Pattern
Intent Attach Additional responsibilities to an
object by dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
AKA Wrapper
Decorator: Motivation
Desire to add responsibilities to individual objects
Two Approaches Inheritance
Choices are made statically Inflexible
Decorator Dynamic Unlimited in number of added
responsibilities
Decorator: Applicability
Use the Decorator Pattern… To add responsibilities to individual
objects dynamically and transparently For responsibilities that can be
withdrawn When extension by subclassing is
impractical
Decorator: Participants
Component Defines the interface for objects that can
have responsibilities added to them dynamically
ConcreteComponent Defines an object to which additional
responsibilities can be attached
Decorator: Participants
Decorator Maintains a reference to a Component
object and defines an interface that conforms to Component’s interface
ConcreteDecorator Adds responsibilities to the component
Decorator: Structure
Decorator: Consequences
Good More Flexibility than static inheritance
Much easier to use than multiple inheritance
Can be used to mix and match features Can add the same property twice
Avoids feature laden classes high up in hierarchy Allows to easily add new features
incrementally
Decorator: Consequences
Bad A decorator and its component aren’t
identical From an object identity point of view, a
decorated component is not identical to the component itself
Don’t rely on object identity when using decorators
Lots of little objects Often end up with systems composed of
lots of little objects Can be hard to learn and debug
Decorator: Implementation
Interface conformance Decorator object’s interface must
conform to the interface of the component it decorates
Omitting the abstract Decorator class If you’re adding just one responsibility,
there’s no need to have the abstract Decorator class
Decorator: Implementation
Keeping Component classes lightweight Component should stick to defining an
interface Changing the skin of an object vs.
changing the guts Strategy vs. Decorator
Decorator: Related Patterns Adapter
Provides new interface vs. changing responsibilities
Composite Can be viewed as a degenerate
composite with only one component Strategy
Skin vs. Guts
Flyweight Pattern
Intent Use sharing to support large numbers of
fine-grained objects efficiently
Flyweight: Motivation
Can be used when an application could benefit from using objects throughout their design, but a naïve implementation would be prohibitively expensive Objects for each character in a
document editor Cost is too great!
Can use flyweight to share characters
Intrinsic vs. Extrinsic
Intrinsic state is stored in the flyweight Information that’s independent of the
flyweight’s context Shared
Extrinsic State depends on and varies with the
flyweight’s context Cannot be shared
Flyweight: Applicability
Use the Flyweight pattern when ALL of the following are true An application uses a large number of
objects Storage costs are high because of the
sheer quantity of objects Most object state can be made extrinsic Many Groups of objects may be replaced
by relatively few shared objects once extrinsic state is removed
The application doesn’t depend on object identity
Flyweight: Participants
Flyweight Declares an interface through which
flyweights can receive and act on extrinsic state
ConcreteFlyweight Implements the Flyweight interface and
adds storage for intrinsic state, if any Must be shareable
Flyweight: Participants
FlyweightFactory Creates and manages flyweight objects Ensures that flyweights are shared
properly Client
Maintains reference to flyweights Computes or stores the extrinsic state of
flyweights
Flyweight: Structure
Flyweight: Consequences
May introduce run-time costs associated with transferring, finding, and/or computing extrinsic state
Costs are offset by space savings
Flyweight: Consequences
Storage savings are a function of the following factors: The reduction in the total number of
instances that comes from sharing The amount of intrinsic state per object Whether extrinsic state is computed or
stored
Flyweight: Consequences
Ideal situation High number of shared flyweights Objects use substantial quantities of
both intrinsic and extrinsic state Extrinsic state is computed
Decorator: Implementation
Removing extrinsic state Success of pattern depends on ability to
remove extrinsic state from shared objects
No help if there are many different kinds of extrinsic state
Ideally, state is computed separately
Flyweight: Implementation
Managing shared objects Objects are shared so clients should not
instantiate FlyweightFactory is used to create and
share objects Garbage collection may not be
necessary
Flyweight: Related Patterns Composite
Often combined with flyweight Provides a logically hierarchical structure
in terms of a directed-acyclic graph with shared leaf nodes
State and Strategy Best implemented as flyweights