Design Patterns Part two
Structural Patterns • Concerned with how classes and objects are composed to form larger structures • Structural class patterns – use inheritance to compose interfaces or implementations. • Structural object patterns – describe ways to compose objects creating new functionality.
The Façade Pattern • Provides a single interface into a subsystem. • Used to separate or simplify the subsystem in the program. • Used in UIs to separate a GUI from the underlying ‘business logic’
Façade – Use When: • A simple interface into a complex subsystem is required. • A subsystem’s details are not or should not be required knowledge for other components. • Subsystems should be compartmentalized, decoupling the system from the ‘black box’. This allows for easier changes within the isolated subsystem, as long as the API for the system isn’t altered • Layering of subsystems is required
Façade - Benefits • Shields clients from subsystem components. • Promotes a weak coupling between subsystems, allows subsystem change without affecting clients. • This pattern helps simplify complex or circular subsystems for outside users. • Possible compile time reduction, as not all components may need to be recompiled.
Façade – Example • You want to make a platform-independent front end to a database • Database runs on any target system • Front end is (almost always) platform dependent • Create a façade API to program the GUI to • Moving to a new platform means reimplementing the GUI, but not the API or the back end code
Implementation Points • Subsystem coupling can be reduced if the façade is an abstract class, and concrete classes implement the subsystem itself. This prevents clients from knowing details about which subsystem is used. • Also, consider the use of interfaces in Java • Judicious use of public and private classes and methods can help provide subsystem independence and encapsulation. (Consider the use of package security in Java)
The Proxy Pattern • The Proxy provides a surrogate or placeholder, often to control access to it. • There are four general categories of proxy. • Used when there needs to be a more versatile reference to an object, or when it is not practical or desired to reference the original. • Example: large image that eats a lot of memory
Proxy Categories • Remote Proxy: Local representative for objects in different spaces. • Virtual Proxy: Creates expensive objects on demand. • Protection Proxy: Controls access, can be similar to a Façade. • Smart Reference: Various value adds, such as object loading, tracking instances, object or database locking.
Proxy Benefits • Remote proxy can hide resident details. • Virtual proxy creates expensive objects on demand, rather than all at startup. • Example: dialog boxes • Protection and Smart Proxies can allow housekeeping an other tasks to be encapsulated.
Proxy – Example • Your program must be ready to display a large number of graphical images, but not all of them can be seen by the user at one time. A virtual proxy could be used to load the image only when needed by the user, so that the time to open the application is not slowed by image loading.
Behavioral Patterns • Concerned with algorithms and the assignment of object responsibilities. • Describe not just the patterns of objects but how they communicate. • Behavioral class patterns use inheritance to distribute behavior to classes. • Behavioral object patterns use object composition rather than inheritance. Often, this describe how a group of objects cooperate to perform a task and what objects need to know about which others.
The Command Pattern Encapsulates a request as an object.
Command – Use When: • Useful to issue requests without knowing details about the operation or recipient. • Objects can be parameterized by an action to perform. • A framework executes a generic command, and the command object is extended to do the application specific method.
Command Benefits • Command allows the calling object to be separate from the one that can perform it. • Commands can be assembled together to form more complex commands. An example of this is the MacroCommand, which will not be discussed here. • Adding new commands is easy, and existing classes won’t have to change.
Command - Benefits • Support can be added for operations undo and redo. • Security can be enhanced by logging user actions through centralized Command objects.
Command – Example • The application you are working on must support a log of all user activity for security purposes. To do this, you use a central command object which will be able to determine what actions a user has taken and can then log them or do whatever actions are required.
Implementation Points • Consider command object intelligence. It can be a simple object between a requestor and a recipient. • For undo/redo, consider what parameters and information must be stored. • If using C++, templates may be used if commands aren’t undoable and don’t require arguments. • Try to limit the number of undoable commands; it bug the user….
The Observer Pattern • Defines a one-to-many dependency or communication flow between objects. When one object is updated, all dependents are notified automatically. • This is one of the most important patterns in GUI development, as it abstracts the notion of the “callback” • Some event occurs (user clicks a button) and something else is notified (function is called)
Observer – Use When: • An abstraction has two aspects, one dependent on the other. Encapsulating these pieces in separate objects lets you vary and reuse them independently. • A change to one object requires changing others; the number to be changed may be dynamic or unknown. • An object should be able to notify others without making assumptions about what the objects are.
Observer - Benefits • Abstracts the coupling between the notifying object and observers. All the notifying object knows is it has a group of observing objects to send a message to. • Good object oriented programming, where a message is sent, but each object’s action is independent. • Support for broadcast communication. Objects can register or deregister as needed, and the notifying object only has to know which objects currently need notification.
Observer - Drawbacks • Care must be taken to ensure that messages sent to observers don’t themselves trigger more messages to be sent, causing an operation to become an infinite loop.
Observer – Example 1 • A user presses the File->Load menu item. An application object called FileLoader is notified (or observes the press) and goes about loading a file.
Observer – Example 2 • A company that makes medical monitors needs a way to display data to nurses and physicians so they can ascertain a patient’s condition quickly and completely. By using an observer, when new data is added to the database, notifications can be sent to multiple observers, say the monitor at the patient’s bedside, the nurses’ station and the physician who happens to be monitoring the patient live in their office at the same time.
Implementation Points • How to map notifying objects to observers. Often down with a simple “connection” function call • Observers may have to know what object is sending the notification, especially if it registers as a listener to more than one notifying object. • Similarly, it may also be more efficient to send data each observer rather than sending an update message and having each observer retrieve it.
A consideration of who triggers the update is very important. Objects can be responsible for sending the notification, but if the code is forgotten at the client, or a bug prevents it from being sent, then the update is never broadcast. • Deleting an observer should not result in a dangling pointer in the notifying object. A way to deal with this could be to make each item an observer of the other so references can be removed when it is deleted.
Push and Pull Models of Implementation. • One extreme is the push, which pushes data to each observer, without knowing if it needs it or not. This may broadcast more information to observers than they need to know, and make code reuse more difficult. • Most GUI toolkits do this • The pull model sends a relatively simple message, which may require each observer to then request potentially identical information. This may hide communication and implementation better, but may result in a more inefficient model.
References • “Design Patterns”, Gamma, Helm, Johnson and Vlissides, Addison-Wesley, 1995