View this PageEdit this PageAttachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide
Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007

observer Design Pattern application

Design Patterns

Here’s the typical problem a human might ask a computer: “I've got this particular programming problem. My initial attempts to solve it have resulted in monolithic classes which don't support several useful cases and are hard to modify. Please show me successful programs where this problem has occurred, the solution taken, and the consequences of each.” Software patterns are a first step in realizing this problem. By documenting the essential technique and rationale behind recurring expert designs, they help people reuse successful practices.
The definition of the design can be expressed as following – determining what kinds of objects should go into the system and what compile-time and run-time relationships they should have. This includes the granularity of objects, inheritance structure, compositional structure, and hooks for extensibility.
One of the most important things is to realize what is a good design. A person can say that besides achieving its functional objectives, a good design should decompose the system into loosely-coupled components with clearly demarcated variabilities. Despite the hype, object-oriented software is not arbitrarily adaptable; adaptability is precisely determined by the system's design. Changing software in unplanned ways will almost surely break it. Furthermore, undocumented variabilities tend to disappear after a careless enhancement or bug fix.
Design is a creative process. Formal methods can empower the creative mind, but they do not fuel creativity. The key to understanding design is knowing the tricks of the trade: what expert designers know that allows them to dream up world-class designs. So, what is it that they know that allows them to be so good at this? Successful design patterns is one of the most important things. Experts reuse time-worn solutions. Until recently, no record of these solutions was ever made, partly because the techniques aren't new (they're recurring patterns) and partly because they are hard to describe. Design patterns are amorphous and intangible. They are not simply pieces of code or box-and-arrow diagrams. Hence, they are not captured by macros, class libraries, or formal notations.
Here is one of the examples of a pattern. Microsoft Foundation Classes (MFC) is a class library for building applications under Windows. Its basic metaphor is visually editing a ‘document,’ which could be a letter, spreadsheet, database, drawing, graph, etc. Any subclass of the Document class will do. The visual representation is provided by an object whose type is a subclass of View. MFC uses separate objects for documents and views, rather than lumping them together. The job of the view object is to ensure that its appearance reflects the state of the document object. MFC does this via a subscribe/notify protocol between the document and view. At run-time, each view object subscribes to a particular document object, and each document object notifies its subscribers whenever it changes. In response, each subscribed view gets an opportunity to update itself. This lets you dynamically attach and detach views of a document. It also allows multiple, consistent views of the same document. Let’s take this example, you have a document which is an array of numbers. It can be simultaneously displayed as a spreadsheet, a bar chart, and pie chart. Modifying the bar chart, say by dragging the height of a bar, will modify the array, which will then notify the other views and let them update themselves to match. This design decouples documents from views, and is indeed a pattern among modern user interface toolkits. However, this design is useful whenever you want to decouple an object from the many possible objects dependent on it. For this reason, it is also a recurring pattern in programming languages, graphics packages, and distributed databases.

The question that people asked was “how can we concisely describe and yet generalize this design?” The idea, started by architect Christopher Alexander, is to fill out a form like this:
Context
The general problem to be solved. When to apply the pattern.
Forces
Potential consequences that a good solution must take into account. Forces are often non-functional, such as reducing coupling or providing a variability.
Solution
Objects that make up the design, their roles, and their relationships. What each object needs to know about the others.
Consequences
The costs and benefits of applying the pattern. How well it resolves the Forces. Used for evaluating competing solutions.
Implementation
Suggestions and pitfalls in implementing the pattern.
Known Uses
Examples of the pattern found in real systems. MFC's Document/View architecture, in pattern form, is called the Observer pattern (see below).

By definition, patterns capture experience, so in a sense they aren't new. Here are three benefits of putting recurring designs into pattern form:
Learning about design
Surveying the possible designs enlarges user’s toolbox and fuels creativity. Studying a pattern and exploring the implementation alternatives allows improving the pattern and makes it easier to come up with new patterns.
Vocabulary
A person can take a fairly complex arrangement of interfaces and run-time interactions between Documents and Views and simplify it to "Observer pattern." This means he/she will be able to conceive of bigger and better designs, because of the higher level of abstraction. Furthermore, users will be automatically reusing techniques that many others have already tested for them.
Documenting policy
Patterns can be used as documentation, to ensure that components stay decoupled and variabilities remain flexible. When someone has a problem with code described as being based on the Observer pattern, a person knowing this patern can immediately answer questions about policy, e.g.
Another example of policy is specifying whether one object contains another versus simply being acquainted with another. Both containment and acquaintance can be implemented in the same way, using pointers or references. But they entail significantly different policies with respect to the destruction, archival, or transmission of the object holding the pointer.


This is a description of an Observer Pattern.

Task: define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. The solution is laid out in the format suggested by architect Christopher Alexander.
Context
Want to maintain consistency between related objects, e.g. data and its visual representation, a filesystem and its cache, or a 3D sphere and the cube which is constrained to abut it.
Forces
Solution
Equip the subject with an interface for subscribing and unsubscribing to change notifications. Also include an interface for querying the subject, so that observers can get the information they need. Equip the observers with an interface for receiving the notifications from the subject.
When the subject is modified, it will notify its subscribers of a change, who will then have the opportunity to query the subject for details and update themselves.
Consequences
Implementation
For maximum speed, each subject can store references to its observers. However, this wastes space when a subject has no observers. For minimum space, use a global table of (subject, observer) pairs. Before an observer can be deleted, it must unsubscribe from its subjects, to avoid dangling pointers. Garbage-collected languages are not exempt from this requirement.
Several variations are possible for reducing communication:


Known Uses

Languages based on constraints generally do not use the Observer pattern, because local propagation is inefficient for complex constraints and is susceptible to cycles. Instead, such languages use a centralized constraint solver.




Link to this Page