250 likes | 277 Views
Learn how to dynamically add responsibilities to objects with the Decorator Pattern and efficiently manage large numbers of objects with the Flyweight Pattern. Understand the advantages, participants, implementation strategies, and consequences of each pattern.
E N D
Matt Klein Decorator Patternflyweight Pattern
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: 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: 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