JavaBeat
Search JavaBeat

Certification Kits
SCJP 1.5 Exam Questions
SCJP 1.6 Exam Questions
SCWCD 1.4 Exam Questions
SCWCD 5.0 Exam Questions
SCBCD 5.0 Exam Questions
SCEA Links
SCEA Home
SCEA Books
Objectives
Mock Exams
Mock Exam - 1
Mock Exam - 2
Mock Exam - 3
Mock Exam - 4
Mock Exam - 5
Mock Exam - 6
Mock Exam - 7
Mock Exam - 8
Mock Exam - 9
Mock Exam - 10
Mock Exam - 11
Tutorials
Certification Links
SCJP 1.4
SCJP 1.5
SCJP 1.6
SCWCD 1.4
SCWCD 5.0
SCBCD 5.0
SCEA
SCEA 5.0
JavaBeat
Home
Articles
Tips
Code
QnA
Forums

SCEA Notes

1. Software Architecture 2. Design Patterns 3. Enterprise Java Beans(EJB) 4. What is internationalization?
5. Legacy Connectivity 6. Protocols 7. Fundamental goals of security

Design Patterns



Iterator

  • Also known as Cursor.
  • Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
  • To traverse the aggregate in different ways, depending on what you want to accomplish.
  • to have more than one traversal pending on the same aggregate object
  • The key idea in this pattern is to take the responsibility for access and traversal out of the aggregate object and put it into an iterator object
  • The Iterator class defines an interface for accessing the aggregate’s elements.
  • An iterator object is responsible for keeping track of the current element; that is, it knows which elements have been traversed already.
  • Separating the traversal mechanism from the List object lets us define iterators for different traversal policies without enumerating them in the List interface. For example, FilteringListIterator might provide access only to those elements that satisfy specific filtering constraints.
  • Use the Iterator pattern
    • to access an aggregate object's contents without exposing its internal representation.
    • to support multiple traversals of aggregate objects.
    • to provide a uniform interface for traversing different aggregate structures (that is, to support polymorphic iteration).
  • The Iterator pattern has three important consequences:
    • It supports variations in the traversal of an aggregate. Complex aggregates may be traversed in many ways. For example, code generation and semantic checking involve traversing parse trees. Code generation may traverse the parse tree inorder or preorder. Iterators make it easy to change the traversal algorithm: Just replace the iterator instance with a different one. You can also define Iterator subclasses to support new traversals.
    • Iterators simplify the Aggregate interface. Iterator's traversal interface obviates the need for a similar interface in Aggregate, thereby simplifying the aggregate's interface.
    • More than one traversal can be pending on an aggregate. An iterator keeps track of its own traversal state. Therefore you can have more than one traversal in progress at once.
  • external iterator / Active iterator à client controls the iteration  à Clients that use an external iterator must advance the traversal and request the next element explicitly from the iterator à more flexible e.g.: easy to compare two collections for equality
  • Internal iterator / Passive Iteratorà  the iterator controls iteration. à The client hands an internal iterator an operation to perform, and the iterator applies that operation to every element in the aggregate. à easier to use, because they define the iteration logic for you.
  • It’s easier just to use an internal iterator (rather than external iterator) for recursive aggregate structures like composite. It can record the current position simply by calling itself recursively, thereby storing the path implicitly in the call stack.
  • Cursor à iterator to store just the state of the iteration. It merely points to the current position in the aggregate  à aggregate defines the traversal algorithm
  •  Cursors are a simple example of the Memento pattern and share many of its implementation issues.
  • Why Cursor??  à If the iterator is responsible for the traversal algorithm, then it's easy to use different iteration algorithms on the same aggregate, and it can also be easier to reuse the same algorithm on different aggregates. On the other hand, the traversal algorithm might need to access the private variables of the aggregate. If so, putting the traversal algorithm in the iterator violates the encapsulation of the aggregate.
  • Robust iterator  à ensures that insertions and removals won't interfere with traversal, and it does it without copying the aggregate.
  • NullIterator  à is a degenerate iterator that's helpful for handling boundary conditions. By definition, a NullIterator is always done with traversal; that is, its IsDone operation always evaluates to true.
  • Composite: Iterators are often applied to recursive structures such as Composites.
  • Factory Method: Polymorphic iterators rely on factory methods to instantiate the appropriate Iterator subclass.
  • Memento : is often used in conjunction with the Iterator pattern. An iterator can use a memento to capture the state of an iteration. The iterator stores the memento internally.

MEDIATOR   Pattern:

 

  • Define an object that encapsulates how a set of objects interact.
  •  promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently
  • Colleagues send and receive requests from a Mediator object.
  • The mediator implements the cooperative behavior by routing requests between the appropriate colleague(s).
  • It limits subclassing. A mediator localizes behavior that otherwise would be distributed among several objects. Changing this behavior requires subclassing Mediator only; Colleague classes can be reused as is.
  • It decouples colleagues. A mediator promotes loose coupling between colleagues. You can vary and reuse Colleague and Mediator classes independently.
  • It simplifies object protocols. A mediator replaces many-to-many interactions with one-to-many interactions between the mediator and its colleagues. One-to-many relationships are easier to understand, maintain, and extend.
  • It abstracts how objects cooperate. Making mediation an independent concept and encapsulating it in an object lets you focus on how objects interact apart from their individual behavior. That can help clarify how objects interact in a system.
  • It centralizes control. The Mediator pattern trades complexity of interaction for complexity in the mediator. Because a mediator encapsulates protocols, it can become more complex than any individual colleague. This can make the mediator itself a monolith that's hard to maintain.
  • Facade differs from Mediator in that it abstracts a subsystem of objects to provide a more convenient interface. Its protocol is unidirectional; that is, Facade objects make requests of the subsystem classes but not vice versa. In contrast, Mediator enables cooperative behavior that colleague objects don't or can't provide, and the protocol is multidirectional.
  • Colleagues can communicate with the mediator using the Observer pattern. Colleagues have to communicate with their mediator when an event of interest occurs. One approach is to implement the Mediator as an Observer using the Observer pattern. Colleague classes act as Subjects, sending notifications to the mediator whenever they change state. The mediator responds by propagating the effects of the change to other colleagues
  • There's no need to define an abstract Mediator class when colleagues work with only one mediator. The abstract coupling that the Mediator class provides lets colleagues work with different Mediator subclasses, and vice versa

FAÇADE Pattern:

  • Provide a unified interface to a set of interfaces in a subsystem.
  • defines a higher-level interface that makes the subsystem easier to use
  • Provides a single, simplified interface to the more general facilities of a subsystem.
  • Clients communicate with the subsystem by sending requests to Facade, which forwards them to the appropriate subsystem object(s).
  • Although the subsystem objects perform the actual work, the facade may have to do work of its own to translate its interface to subsystem interfaces.
  • Clients that use the facade don't have to access its subsystem objects directly.
  • Facade

·         Knows which subsystem classes are responsible for a request.

·         Delegates client requests to appropriate subsystem objects.

  • Subsystem classes

·         Implement subsystem functionality.

·         Handle work assigned by the Facade object.

·         Have no knowledge of the facade; that is, they keep no references to it.

  • The Facade pattern offers the following benefits:
    • It shields clients from subsystem components, thereby reducing the number of objects that clients deal with and making the subsystem easier to use.
    • It promotes weak coupling between the subsystem and its clients. Often the components in a subsystem are strongly coupled. Weak coupling lets you vary the components of the subsystem without affecting its clients. Facades help layer a system and the dependencies between objects. They can eliminate complex or circular dependencies. This can be an important consequence when the client and the subsystem are implemented independently.
    • Reducing compilation dependencies is vital in large software systems. You want to save time by minimizing recompilation when subsystem classes change. Reducing compilation dependencies with facades can limit the recompilation needed for a small change in an important subsystem. A facade can also simplify porting systems to other platforms, because it's less likely that building one subsystem requires building all others.
    • It doesn't prevent applications from using subsystem classes if they need to. Thus you can choose between ease of use and generality.
  • Use the Facade pattern when

·         You want to provide a simple interface to a complex subsystem. Subsystems often get more complex as they evolve. Most patterns, when applied, result in more and smaller classes. This makes the subsystem more reusable and easier to customize, but it also becomes harder to use for clients that don't need to customize it. A facade can provide a simple default view of the subsystem that is good enough for most clients. Only clients needing more customizability will need to look beyond the facade.

·         There are many dependencies between clients and the implementation classes of an abstraction. Introduce a facade to decouple the subsystem from clients and other subsystems, thereby promoting subsystem independence and portability.

·         You want to layer your subsystems. Use a facade to define an entry point to each subsystem level. If subsystems are dependent, then you can simplify the dependencies between them by making them communicate with each other solely through their facades.

1.        Abstract Factory can be used with Facade to provide an interface for creating subsystem objects in a subsystem-independent way. Abstract Factory can also be used as an alternative to Facade to hide platform-specific classes.

2.       Mediator is similar to Facade in that it abstracts functionality of existing classes. However, Mediator's purpose is to abstract arbitrary communication between colleague objects, often centralizing functionality that doesn't belong in any one of them. A mediator's colleagues are aware of and communicate with the mediator instead of communicating with each other directly. In contrast, a facade merely abstracts the interface to subsystem objects to make them easier to use; it doesn't define new functionality, and subsystem classes don't know about it.

3.        Usually only one Facade object is required. Thus Facade objects are often Singletons .


OBSERVER Pattern:

 

  • Also Known As Dependents, Publish-Subscribe
  • Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
  • Maintain consistency between related objects by making the classes loosely coupled, because that increases their reusability.
  • Abstract coupling between Subject and Observer. All a subject knows is that it has a list of observers, each conforming to the simple interface of the abstract Observer class. The subject doesn't know the concrete class of any observer. Thus the coupling between subjects and observers is abstract and minimal. Because Subject and Observer aren't tightly coupled, they can belong to different layers of abstraction in a system. A lower-level subject can communicate and inform a higher-level observer, thereby keeping the system's layering intact
  • Support for broadcast communication. Unlike an ordinary request, the notification that a subject sends needn't specify its receiver. The notification is broadcast automatically to all interested objects that subscribed to it. The subject doesn't care how many interested objects exist; its only responsibility is to notify its observers. This gives you the freedom to add and remove observers at any time. It's up to the observer to handle or ignore a notification.
  • Unexpected updates. Because observers have no knowledge of each other's presence, they can be blind to the ultimate cost of changing the subject. A seemingly innocuous operation on the subject may cause a cascade of updates to observers and their dependent objects. Moreover, dependency criteria that aren't well-defined or maintained usually lead to spurious updates, which can be hard to track down.
  • Use the Observer pattern in any of the following situations:
    • When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.
    • When a change to one object requires changing others, and you don't know how many objects need to be changed.
    • When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.  

 


PROTOTYPE Pattern:

 

  • Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
  • Prototype  à declares an interface for cloning itself.
  • ConcretePrototype  à  implements an operation for cloning itself.
  • Client  à  creates a new object by asking a prototype to clone itself.
  • A client can install and remove prototypes at run-time.
  • Specifying new objects by varying values. Highly dynamic systems let you define new behavior through object composition—by specifying values for an object's variables, for example—and not by defining new classes. You effectively define new kinds of objects by instantiating existing classes and registering the instances as prototypes of client objects. A client can exhibit new behavior by delegating responsibility to the prototype. This kind of design lets users define new "classes" without programming. In fact, cloning a prototype is similar to instantiating a class. The Prototype pattern can greatly reduce the number of classes a system needs.
  • Specifying new objects by varying structure. Many applications build objects from parts and subparts. Editors for circuit design, for example, build circuits out of subcircuits.1 For convenience, such applications often let you instantiate complex, user-defined structures, say, to use a specific subcircuit again and again. The Prototype pattern supports this as well. We simply add this subcircuit as a prototype to the palette of available circuit elements. As long as the composite circuit object implements Clone as a deep copy, circuits with different structures can be prototypes.
  • Reduced subclassing. Factory Method often produces a hierarchy of Creator classes that parallels the product class hierarchy. The Prototype pattern lets you clone a prototype instead of asking a factory method to make a new object. Hence you don't need a Creator class hierarchy at all.
  • Configuring an application with classes dynamically. Some run-time environments let you load classes into an application dynamically
  • Use the Prototype pattern
    • when a system should be independent of how its products are created, composed, and represented; and
    • when the classes to instantiate are specified at run-time, for example, by dynamic loading; or to avoid building a class hierarchy of factories that parallels the class hierarchy of products; or 
    • When instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state.
  • The main liability of the Prototype pattern is that
    • Each subclass of Prototype must implement the Clone operation, which may be difficult. For example, adding Clone is difficult when the classes under consideration already exist.
    • Implementing Clone can be difficult when their internals include objects that don't support copying or have circular references
  • Prototype and Abstract Factory are competing patterns in some ways, as we discuss at the end of this chapter. They can also be used together, however. An Abstract Factory might store a set of prototypes from which to clone and return product objects.
  • Designs that make heavy use of the Composite  and Decorator  patterns often can benefit from Prototype as well.

 

 


Proxy Pattern:

 

  • Also Known As surrogate
  • Intent à  Provide a surrogate or placeholder for another object to control access to it.
  • One reason for controlling access to an object is to defer the full cost of its creation and initialization until we actually need to use it.
  • Proxy is applicable whenever there is a need for a more versatile or sophisticated reference to an object than a simple pointer.
  • Remote proxy  à   also called Ambassador  à provides a local representative for an object in a different address space.
  • Remote proxy can hide the fact that an object resides in a different address space.
  • Virtual proxy  à creates expensive objects on demand.
  • Protection proxy  à controls access to the original object. Protection proxies are useful when objects should have different access rights.
  • Smart reference  à is a replacement for a bare pointer that performs additional actions when an object is accessed. Typical uses include
    • Counting the number of references to the real object so that it can be freed automatically when there are no more references (also called smart pointers [Ede92]).
    • Loading a persistent object into memory when it's first referenced.
    • Checking that the real object is locked before it's accessed to ensure that no other object can change it.
  • Both protection proxies and smart references allow additional housekeeping tasks when an object is accessed.
  • Provides an interface identical to Subject's so that a proxy can by substituted for the real subject.
  • Controls access to the real subject and may be responsible for creating and deleting it.
  • Proxy forwards requests to RealSubject when appropriate, depending on the kind of proxy.
  • copy-on-write à related to creation on demand à another optimization that the Proxy pattern can hide from the client. à Copying a large and complicated object  only if it is by using proxy.
  • Vs Adapter   à  an adapter provides a different interface to the object it adapts. In contrast, a proxy provides the same interface as its subject. However, a proxy used for access protection might refuse to perform an operation that the subject will perform, so its interface may be effectively a subset of the subject's.
  •  Vs Decorator  à although decorators can have similar implementations as proxies, decorators have a different purpose. A decorator adds one or more responsibilities to an object, whereas a proxy controls access to an object.
  • Proxies vary in the degree to which they are implemented like a decorator. A protection proxy might be implemented exactly like a decorator.
  • On the other hand, a remote proxy will not contain a direct reference to its real subject but only an indirect reference, such as "host ID and local address on host." A virtual proxy will start off with an indirect reference such as a file name but will eventually obtain and use a direct reference.

ADAPTER Pattern:

 

·         Also Known As Wrapper  ( Decorator is also known as Wrapper )

·         Intent  à to convert the interface of a class into another interface clients expect.

·         Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

·         Participants

o        Target à defines the domain-specific interface that Client uses.

o        Client  à collaborates with objects conforming to the Target interface.

o        Adaptee  à defines an existing interface that needs adapting.

o        Adapter  à adapts the interface of Adaptee to the Target interface.

·         Clients call operations on an Adapter instance. In turn, the adapter calls Adaptee operations that carry out the request.

·         Use the Adapter pattern when

o        You want to use an existing class, and its interface does not match the one you need.

o        You want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces.

o        (Object adapter only) you need to use several existing subclasses, but it's impractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class.

·          Vs Bridge has a structure similar to an object adapter, but Bridge has a different intent: It is meant to separate an interface from its implementation so that they can be varied easily and independently. An adapter is meant to change the interface of an existing object.

·         Vs Decorator enhances another object without changing its interface. A decorator is thus more transparent to the application than an adapter is. As a consequence, Decorator supports recursive composition, which isn't possible with pure adapters.

·         Vs Proxy defines a representative or surrogate for another object and does not change its interface

·         class adapter

o        Adapts Adaptee to Target by committing to a concrete Adapter class. As a consequence, a class adapter  won't work when we want to adapt a class and all its subclasses.

o        Lets Adapter override some of Adaptee's behavior, since Adapter is a subclass of Adaptee.

o        Introduces only one object and no additional pointer indirection is needed to get to the adaptee.

·         object adapter

o        Lets a single Adapter work with many Adaptees that is, the Adaptee itself and all of its subclasses (if any). The Adapter can also add functionality to all Adaptees at once.

o        Makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself.

·         Pluggable adapters à  classes with built-in interface adaptation à a class is more reusable when you minimize the assumptions other classes must make to use it. à  Interface adaptation lets us incorporate our class into existing systems that might expect different interfaces to the class.

·         Two-way adapters  à to provide transparency à an adapted object no longer conforms to the Adaptee interface, so it can't be used as is wherever an Adaptee object can. Two-way adapters can provide such transparency.  à Specifically, they're useful when two different clients need to view an object differently.


COMPOSITE Pattern:

  • Compose objects into tree structures to represent part-whole hierarchies.
  • Composite lets clients treat individual objects and compositions of objects uniformly using recursive composition.
  • Defines class hierarchies consisting of primitive objects and composite objects. Primitive objects can be composed into more complex objects, which in turn can be composed, and so on recursively. Wherever client code expects a primitive object, it can also take a composite object.
  • Makes the client simple. Clients can treat composite structures and individual objects uniformly. Clients normally don't know (and shouldn't care) whether they're dealing with a leaf or a composite component. This simplifies client code, because it avoids having to write tag-and-case-statement-style functions over the classes that define the composition.
  • Makes it easier to add new kinds of components. Newly defined Composite or Leaf subclasses work automatically with existing structures and client code. Clients don't have to be changed for new Component classes.
  • Can make your design overly general. The disadvantage of making it easy to add new components is that it makes it harder to restrict the components of a composite. Sometimes you want a composite to have only certain components. With Composite, you can't rely on the type system to enforce those constraints for you. You'll have to use run-time checks instead.

 

Clients use the Component class interface to interact with objects in the composite structure. If the recipient is a Leaf, then the request is handled directly. If the recipient is a Composite, then it usually forwards requests to its child components, possibly performing additional operations before and/or after forwarding

  • Participants
    • Component
      • declares the interface for objects in the composition.
      • implements default behavior for the interface common to all classes, as appropriate.
      • declares an interface for accessing and managing its child components.
      • (optional) defines an interface for accessing a component's parent in the recursive structure, and implements it if that's appropriate.
    • Leaf
      • represents leaf objects in the composition. A leaf has no children.
      • defines behavior for primitive objects in the composition.
    • Composite
      • defines behavior for components having children.
      • stores child components.
      • implements child-related operations in the Component interface.
    • Client  à manipulates objects in the composition through the Component interface.
  • Often the component-parent link is used for a Chain of Responsibility.
  • Decorator is often used with Composite. When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface with operations like Add, Remove, and GetChild.
  • Flyweight lets you share components, but they can no longer refer to their parents.
  • Iterator can be used to traverse composites.
  • Visitor localizes operations and behavior that would otherwise be distributed across Composite and Leaf classes.

COMMAND Pattern:

 

  • Also Known As Action, Transaction
  • Intent à Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
  • To issue requests to objects without knowing anything about the operation being requested or the receiver of the request.
  • Consequences:
    • Command decouples the object that invokes the operation from the one that knows how to perform it.  i.e. decouple invoker from receiver
    • Commands are first-class objects. They can be manipulated and extended like any other object.
    • You can assemble commands into a composite command.. In general, composite commands are an instance of the Composite pattern.
    • It's easy to add new Commands, because you don't have to change existing classes.
  • Use the Command pattern when you want to
    • Parameterize objects by an action to perform.. Commands are an object-oriented replacement for callbacks.
    • Specify, queue, and execute requests at different times. A Command object can have a lifetime independent of the original request. If the receiver of a request can be represented in an address space-independent way, then you can transfer a command object for the request to a different process and fulfill the request there.
    • Support undo. The Command's Execute operation can store state for reversing its effects in the command itself. The Command interface must have an added Unexecute operation that reverses the effects of a previous call to Execute. Executed commands are stored in a history list. Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling Unexecute and Execute, respectively.
    • Support logging changes so that they can be reapplied in case of a system crash. By augmenting the Command interface with load and store operations, you can keep a persistent log of changes. Recovering from a crash involves reloading logged commands from disk and reexecuting them with the Execute operation.
    • Structure a system around high-level operations built on primitives operations. Such a structure is common in information systems that support transactions. A transaction encapsulates a set of changes to data. The Command pattern offers a way to model transactions. Commands have a common interface, letting you invoke all transactions the same way. The pattern also makes it easy to extend the system with new transactions.

Collaborations

·         The client creates a ConcreteCommand object and specifies its receiver.

·         An Invoker object stores the ConcreteCommand object.

·         The invoker issues a request by calling Execute on the command. When commands are undoable, ConcreteCommand stores state for undoing the command prior to invoking Execute.

·         The ConcreteCommand object invokes operations on its receiver to carry out the request.

·         Command decouples the invoker from the receiver (and the request it carries out).

                      Participants:

·         Command   à declares an interface for executing an operation.

·         ConcreteCommand  à

        • Defines a binding between a Receiver object and an action.
        • Implements Execute by invoking the corresponding operation(s) on Receiver.

·         Client (Application) à creates a ConcreteCommand object and sets its receiver.

·         Invoker à asks the command to carry out the request.

·         Receiver à  knows how to perform the operations associated with carrying out a request. Any class may serve as a Receiver.

  • A Composite can be used to implement MacroCommands.
  • A Memento can keep state the command requires to undo its effect.
  • A command that must be copied before being placed on the history list acts as a Prototype

BRIDGE Pattern:

 

  • Also Known As Handle/Body
  • Decouple an abstraction from its implementation so that the two can vary independently.
  •  Inheritance binds an implementation to the abstraction permanently, which makes it difficult to modify, extend, and reuse abstractions and implementations independently
  • Use the Bridge pattern when
    • You want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for example, when the implementation must be selected or switched at run-time.
    • Both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern lets you combine the different abstractions and implementations and extend them independently.
    • Changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled.
    • You want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client.
  • Abstraction forwards client requests to its Implementor object.
  • consequences:
    • Decoupling interface and implementation. An implementation is not bound permanently to an interface. The implementation of an abstraction can be configured at run-time. It's even possible for an object to change its implementation at run-time.
    • Decoupling Abstraction and Implementor also eliminates compile-time dependencies on the implementation. Changing an implementation class doesn't require recompiling the Abstraction class and its clients. This property is essential when you must ensure binary compatibility between different versions of a class library.
    • Furthermore, this decoupling encourages layering that can lead to a better-structured system. The high-level part of a system only has to know about Abstraction and Implementor.
    • Improved extensibility. You can extend the Abstraction and Implementor hierarchies independently.
    • Hiding implementation details from clients. You can shield clients from implementation details, like the sharing of implementor objects and the accompanying reference count mechanism (if any).
  • An Abstract Factory can create and configure a particular Bridge.
  • The Adapter  pattern is geared toward making unrelated classes work together. It is usually applied to systems after they're designed. Bridge, on the other hand, is used up-front in a design to let abstractions and implementations vary independently.

FLYWEIGHT Pattern:

 

  • Intent à Use sharing to support large numbers of fine-grained objects efficiently.
  • A flyweight is a shared object that can be used in multiple contexts simultaneously.
  • The flyweight acts as an independent object in each context—it's indistinguishable from an instance of the object that's not shared.
  • Flyweights cannot make assumptions about the context in which they operate.
  • Intrinsic state  à stored in the flyweight à information that's independent of the flyweight's context à sharable.
  •  Extrinsic state à depends on and varies with the flyweight's context àcan't be shared. à Client objects are responsible for passing extrinsic state to the flyweight when it needs it.
  • Flyweights model concepts or entities that are normally too plentiful to represent with objects.
  • The Flyweight pattern's effectiveness depends heavily on how and where it's used. Apply 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. Since flyweight objects may be shared, identity tests will return true for conceptually distinct objects.
  • Savings = f (flyweights no. + amt of intrinsic state + amt of extrinsic state + extrinsic stored/computed )
  • The more flyweights are shared, the greater the storage savings. The savings increase with the amount of shared state.
  • The greatest savings occur when the objects use substantial quantities of both intrinsic and extrinsic state, and the extrinsic state can be computed rather than stored. Then you save on storage in two ways: Sharing reduces the cost of intrinsic state, and you trade extrinsic state for computation time.
  • Because objects are shared, clients shouldn't instantiate them directly. FlyweightFactory lets clients locate a particular flyweight.
  • FlyweightFactory objects often use an associative store to let clients look up flyweights of interest
  • Sharability also implies some form of reference counting or garbage collection to reclaim a flyweight's storage when it's no longer needed.
  • Related Patterns:
    • The Flyweight pattern is often combined with the Composite pattern to implement a logically hierarchical structure in terms of a directed-acyclic graph with shared leaf nodes.
    • It's often best to implement State and Strategy  objects as flyweights.

MEMENTO Pattern:


  • Also Known As Token
  •  Intent à Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.
  •  A memento is an object that stores a snapshot of the internal state of another object—the memento's originator.
  • The undo mechanism will request a memento from the originator when it needs to checkpoint the originator's state. The originator initializes the memento with information that characterizes its current state. Only the originator can store and retrieve information from the memento—the memento is "opaque" to other objects.
  • Use the Memento pattern when
    • a snapshot of (some portion of) an object's state must be saved so that it can be restored to that state later, and
    • a direct interface to obtaining the state would expose implementation details and break the object's encapsulation

      Participants:

·         Memento

o        stores internal state of the Originator object. The memento may store as much or as little of the originator's internal state as necessary at its originator's discretion.

o        protects against access by objects other than the originator. Mementos have effectively two interfaces. Caretaker sees a narrow interface to the Memento—it can only pass the memento to other objects. Originator, in contrast, sees a wide interface, one that lets it access all the data necessary to restore itself to its previous state. Ideally, only the originator that produced the memento would be permitted to access the memento's internal state.

·         Originator

o        creates a memento containing a snapshot of its current internal state.

o        uses the memento to restore its internal state.

·         Caretaker

o        is responsible for the memento's safekeeping.

o        never operates on or examines the contents of a memento.

·         A caretaker requests a memento from an originator, holds it for a time, and passes it back to the originator, as the following interaction diagram illustrates

·         Sometimes the caretaker won't pass the memento back to the originator, because the originator might never need to revert to an earlier state.

·         Mementos are passive. Only the originator that created a memento will assign or retrieve its state.

·         The Memento pattern has several consequences:

o        Preserving encapsulation boundaries. Memento avoids exposing information that only an originator should manage but that must be stored nevertheless outside the originator. The pattern shields other objects from potentially complex Originator internals, thereby preserving encapsulation boundaries.

o        It simplifies Originator. In other encapsulation-preserving designs, Originator keeps the versions of internal state that clients have requested. That puts all the storage management burden on Originator. Having clients manage the state they ask for simplifies Originator and keeps clients from having to notify originators when they're done.

o        Using mementos might be expensive. Mementos might incur considerable overhead if Originator must copy large amounts of information to store in the memento or if clients create and return mementos to the originator often enough. Unless encapsulating and restoring Originator state is cheap, the pattern might not be appropriate.

o        Defining narrow and wide interfaces. It may be difficult in some languages to ensure that only the originator can access the memento's state.

o        Hidden costs in caring for mementos. A caretaker is responsible for deleting the mementos it cares for. However, the caretaker has no idea how much state is in the memento. Hence an otherwise lightweight caretaker might incur large storage costs when it stores mementos.

·         Related Patterns:

o        Command : Commands can use mementos to maintain state for undoable operations.

o        Iterator : Mementos can be used for iteration

 


JavaBeat Website (2004-2008), India
javabeat | about us | useful resources
Copyright (2004 - 2008), JavaBeat