Here isOpenBook in its most rudimentary form: public class MyOpenBook : Bridge { // Combination of a virtual and authentication proxy SpaceBook mySpaceBook; string name; static int u
Trang 1The second implementation of theBridge interface in this example also happens to
be aProxyto SpaceBook Most of theProxymechanisms have been stripped out, andall that remains is the smart proxy operation of keeping a serial count of users Here
isOpenBook in its most rudimentary form:
public class MyOpenBook : Bridge {
// Combination of a virtual and authentication proxy
SpaceBook mySpaceBook;
string name;
static int users;
public MyOpenBook (string n) {
public void Add(string friend, string message) {
mySpaceBook.Add(friend, name + " said: "+message);
myOpenBook.Add(who, what+" you");
static class OpenBookExtensions {
public static void SuperPoke (this Portal me, string who, string what) { me.Add(who, what+" you");
}
}
Trang 2Example: OpenBook | 43
and call it the same way we call the other methods:
tom.SuperPoke("Judith-1","hugged");
Extension methods are one of the new features in C# 3.0
The full program for the OpenBook extension is given in Example 2-6 TheSpaceBookandMySpaceBookclasses from Example 2-4 were not altered in any way andare given as headers only to save space In this output, Judith has switched to Open-Book and therefore has the name Judith-1 Tom, as the second OpenBook user, isgiven the name Tom-2
C# 3.0 Feature—Extension Methods
Extension methods allow developers to add new methods to an existing type withouthaving to create an inherited class or to recompile the original Thus, you can addmethods to classes for which you might not even have the sources (e.g., System String) An extension method is defined the same way as any other, with twostipulations:
• It is declared asstatic in an outer-level static, nongeneric class.
• The type it is extending is declared as the first parameter, preceded bythis.The method can then be called as an instance method on an object of the type that hasbeen extended
cf C# Language Specification Version 3.0, September 2007, Section 10.6.9
Example 2-6 Bridge pattern example code—OpenBook
using System;
using System.Collections.Generic;
// Bridge Pattern Example Judith Bishop Dec 2006, Aug 2007
// Extending SpaceBook with a second implementation via a Portal
Trang 3// Bridge
interface Bridge {
void Add(string message);
void Add(string friend, string message);
void Poke(string who);
public class MySpaceBook { }
// A Proxy with little to do
// Illustrates an alternative implementation of the Bridge pattern public class MyOpenBook : Bridge {
// Combination of a virtual and authentication proxy
SpaceBook myOpenBook;
string name;
static int users;
public MyOpenBook (string n) {
public void Add(string friend, string message) {
myOpenBook.Add(friend, name + " : "+message);
static class OpenBookExtensions {
public static void SuperPoke (this Portal me, string who, string what) { me.Add(who, what+" you");
}
}
// The Client
class BridgePattern : SpaceBookSystem {
static void Main ( ) {
Example 2-6 Bridge pattern example code—OpenBook (continued)
Trang 4Example: OpenBook | 45
Portal me = new Portal(new MyOpenBook("Judith"));
me.Add("Hello world");
me.Add("Today I worked 18 hours");
Portal tom = new Portal(new MyOpenBook("Tom"));
Today I worked 18 hours
Tom poked you
Tom : hugged you
===================================
======== Judith-1's SpaceBook =========
Hello world
Today I worked 18 hours
Tom poked you
Tom : hugged you
Tom : Poor you
Trang 5Bridge is a very simple, but very powerful pattern Given a single implementation, wecan add a second one together with a Bridge and an Abstraction and achieveconsiderable generality over the original design
A well-quoted use of the Bridge pattern is in graphics, where different displays havedifferent capabilities and drivers These would be the implementations of the Bridgepattern, and the Bridge would be an interface of their essential capabilities TheClientcalls theAbstractionto display something, and theAbstractioncan examinethe properties of the one or more Bridgeinstances (drivers) it is holding and selectthe most appropriate one for the task
Exercise
1 Although some limited operations can be added to OpenBook, the fact thatsome fundamental ones, such as the page header, are embedded in the privateSpaceBookclass makes real change difficult Assuming that you can negotiate anupgrade with the developers of SpaceBook, make a proposal, including a UMLdiagram, for the long-term design of an extensible system Implement it
Pattern Comparison
The careful reader might have noticed that the three patterns described in this ter seem to offer much the same service At a high level, they are all helping to extendclasses in novel ways, and they all provide alternatives to inheritance A summary ofwhen each pattern might be used was provided at the end of each section Becausethis is also a programming book, we’ll now summarize the object mechanisms thepatterns use (see Table 2-2) and draw conclusions about their comparative opera-tion This summary is based on the UML diagrams and theory code for each of thepatterns
chap-In each pattern, we can identify four roles, which can fall under the headings
origi-nal, new, interface, and client The actual names given to these meta-roles are shown
in the first three rows of the table Note that the Bridge pattern can work in twoways In our examples, we used the “Bridge-up” option We assumed that we had
Use the Bridge pattern when…
You can:
• Identify that there are operations that do not always need to be implemented in the same way
You want to:
• Completely hide implementations from clients
• Avoid binding an implementation to an abstraction directly
• Change an implementation without even recompiling an abstraction
• Combine different parts of a system at runtime
Trang 6Pattern Comparison | 47
one implementation already and wanted to share its interface with other tations yet to be built To do so, we needed to create anAbstractionthat was closelyconnected to theBridgeinterface An equally valid application for the Bridge patternwould be to have an original abstraction in mind and to build it hand-in-hand withthe implementations (the “Bridge-down” approach)
implemen-As you can see in the fourth row of the table, variations are found in the clients Forexample, the Decorator pattern aggregates the interface so that it can share decora-tions; it provides the original as a construction parameter The Bridge-up patterndoes the same To make this more concrete, here are the two statements from theclients:
// Decorator
Display(new DecoratorA(new IComponent( ));
// Bridge-up
Console.WriteLine(new Abstraction(new ImplementationA( )).Operation( ));
The fifth row shows what objects are invoked in the pattern The Decorator patterncan call the original components or the decorators, but the Bridge pattern variationsonly call one or the other The Proxy pattern both aggregates and invokes only thenew classes
Table 2-2 Comparison of Decorator, Proxy, and Bridge patterns
Original Component Subject Abstraction Implementation
Client aggregates New with interface New Original with new New with original
Client activates Original and new New Original New
Original changed by Implementing the
interface
No change Aggregating the
interface
Implementing the interface
New classes Aggregate the
interface Implement the interface
Aggregate the original Implement the interface
Implement the interface
Aggregate the interface
Operation routed From new to original From new to original From original to new From new to original
Trang 7The next row itemizes how the original changes as a result of the pattern Only theProxy pattern enables the original to remain completely unchanged The Decoratorpattern relies on there being an interface that everyone implements, which mighthave to be added after the original classes are developed The Bridge pattern is moreclosely coupled, and there is an understanding that the original must incorporateconsiderable references to the rest of the system.
All the patterns rely on rerouting operations The last row in the table shows that thererouting is always done from the new code back to the original; in the case of theBridge pattern, it just depends on which class is called new and which class is calledthe original It is worth noting that in real-time applications, where reaction time isimportant, the overhead of the time for rerouting the operations might not beacceptable
Trang 8Computer applications that specialize in grouping data abound these days Consider
a music playlist in iTunes or a digital photo album in Flickr or iPhoto (Figure 3-1).Items are put in a large list, which is then given structure separately
Trang 9Looking at the screenshot from iPhoto, we can see that there are different ways ofviewing the photos that have been imported: chronologically or by named event A sin-gle photo can appear in many albums (“Last Roll,” “2007,” and “Switzerland,” forexample) Creating an album forms a composite object but does not entail actuallycopying the photos In this context, the important point about the Composite pattern
is that the operations carried out on photos and albums of photos should have thesame names and effects, even though the implementations are different For example,the user should be able to display a photo or an album (that contains photos) Simi-larly, deletions of a single photo or an album should behave in the same way
Design
The Composite pattern is one of the simplest there is, on the face of it It has to dealwith two types:Components and Composites of those components Both types agree toconform to an interface of common operations Composite objects consist ofComponents, and in most cases, operations on aCompositeare implemented by callingthe equivalent operations for its Componentobjects See Figure 3-2 for the UML dia-gram for this pattern
The essential players in the Composite pattern UML diagram are:
Trang 10Implements the operations as applicable to composite objects, using (or accessing)
a list of components kept locally and probably using the equivalent Componentoperations
The client deals only with theIComponent interface, which simplifies its task
Figure 3-2 Composite pattern UML diagram
Q U I Z
Match the Composite Pattern Players with the iPhoto Illustration
To test whether you understand the Composite pattern, cover the lefthand column ofthe table below and see if you can identify the players among the items from the illus-trative example (Figure 3-1), as shown in the righthand column Then check youranswers against the lefthand column
IComponent Component Composite Operation
A visible entity in iPhoto
A single photo
An album of photos Open and view
Trang 11Although our illustration referred to photos and albums, the design and tion of the Composite pattern is completely independent from the kind of basic com-ponent being handled We could equally well be dealing with groups of people or bankaccount portfolios The composite operations, however, have to iterate through astructure of these components To realize both the flexibility of components of any
implementa-type and a connection between leaf and composite, we can use the C# generics feature.
By declaringIComponent,Component, andCompositeas generic types, we create an mentation of the Composite pattern that can be instantiated in a practical example
imple-For the Composite pattern, we will not create a program, but a
namespace containing two classes,Composite and Component , and an
interface, IComponent
Starting with theIComponentinterface, we declare it as a generic of typeT Then each
of the anticipated operations follows:
public interface IComponent <T> {
void Add(IComponent <T> c);
IComponent <T> Remove(T s);
IComponent <T> Find(T s);
string Display(int depth);
T Item {get; set;}
}
C# Feature—Generics
Generics are an extension to the type system whereby structs, classes, interfaces, gates, and methods can be parameterized with types For example, a generic type likeList<T>is a generator for constructed types likeList<string>andList<Person> All thecollections in the NET Framework library used by C# are available in generic form.They includeDictionary, Stack, Queue, and List, plus variations on them There arealso generic methods such asSortandBinarySearch These require the types they areworking on to implement theIComparerinterface so that comparisons between ele-ments can be done correctly
dele-To specify a generic type or method, use the generic parameters in angle brackets, as
in<T>or<T, P> The generic type can be used to specify further generic elements, againusing the<T> format, or it can be used normally as a type, as in T.
To construct an actual type or method from a generic one, supply actual types for each
of the generic parameters, as in<string>.
cf C# Language Specification Version 3.0, September 2007, Section 10.1.3
Trang 12Composite Pattern | 53
Because the types will be in a separate namespace, they must all be
declared as public
Why doAdd,Remove, andFindrefer toIComponent <T>andRemoveandFindrefer toT
as well? What is the difference between <T> and T? Recall that an object of typeIComponentis either aComponentor aCompositeand will have state associated withbeing anIComponent, in addition to the actual value of the element it is storing Theelement is of the type T, so in the case ofFindandRemove, we pass as parametersthe actual element values of typeT For example, if the interface were instantiatedwithTas anImage, we would pass anImageobject toFindand in return get a refer-ence to anIComponentobject The returned object would contain theImageobject ifthe search were successful
The last line of the interface is interesting because it introduces a new syntax for erties in classes Before C# 3.0, this new syntax was only present in interfaces It hasnow been extended to classes as well and makes programs shorter and easily readable
prop-Now, let’s consider how the Componentclass would be implemented in accordancewith theIComponent interface, as in the namespace shown in Example 3-1
C# 3.0 Feature—Properties and Accessors
A property gives controlled access to the private local state of an object, either directly
to its fields or via some computation Properties define one or two accessors:getand/
orset The most common form of a property is:
public type Field {get; set;}
whereFieldis an identifier This declaration creates a private field and makes it sible for public reading and writing via the nameField
acces-By placing such properties in an interface, we are effectively requiring classes to supplyproperty accessors as well as the usual methods when implementing the interface.Properties can omit either thegetor thesetaccessor; it is more typical to omit theset,which makes the property read-only
Properties can also compute the result of agetorset, in which case, the expanded tax is:
syn-public type Field {
get { statements; return expression; }
set { statements including reference to value; }
Trang 13Example 3-1 Composite pattern—namespace code
17 public class Component <T> : IComponent <T> {
18 public T Name {get; set;}
24 public void Add(IComponent <T> c) {
25 Console.WriteLine("Cannot add to an item");
26 }
27
28 public IComponent <T> Remove(T s) {
29 Console.WriteLine("Cannot remove directly");
30 return this;
31 }
32
33 public string Display(int depth) {
34 return new String('-', depth) + Name+"\n";
46 public class Composite <T> : IComponent <T> {
47 List <IComponent <T>> list;
Trang 14Composite Pattern | 55
The namespace starts off with the definition of the interface with its four methodsand one property Then follows theComponentclass Not all ofIComponent’s methodsare meaningful forComponents Adding and removing are done only inComposites, so
53 list = new List <IComponent <T>> ( );
62 // Finds the item from a particular point in the structure
63 // and returns the composite from which it was removed
64 // If not found, return the point as given
65 public IComponent <T> Remove(T s) {
76 // Recursively looks for an item
77 // Returns its reference or else null
78 public IComponent <T> Find (T s) {
90 // Displays items in a format indicating their level in the composite structure
91 public string Display(int depth) {
92 StringBuilder s = new StringBuilder(new String('-', depth));
93 s.Append("Set "+ Name + " length :" + list.Count + "\n");
94 foreach (IComponent <T> component in list) {
Trang 15a simple error message is written out (see the upcoming “Exercises” section for anextension on this point) In the Component’s Find method (lines 37–42), the classrelies on the actual type parameter forThaving anEqualsmethod If it does not, thegeneric instantiation will fail at compile time.
TheDisplay method (lines 33–35) also assumes that the field accessed by theNameproperty has a ToString method defined In fact, only string-like types will workproperly here, so it is likely that theDisplaymethod should be defined later (see theupcoming “Exercises” section.)
TheCompositeclass also implements theIComponentinterface (line 46) TheFindandRemovemethods of the Compositeare more elaborate than those in theComponentsothat they can handle arbitrary structures of composites and components Let’s look
at some of the more interesting statements:
• The Composite keeps as a list a local structure that consists ofComponents andComposites (line 47) When the contents areComposites, a new object is created,
as well as a new list The list is declared as:
List <IComponent <T>> list;
This shows that an open generic type can be used as a parameter to anothergeneric type
• The logic ofRemove(lines 65–74) is that we first find the item in the structureand then, if it is there, we remove it from the list structure held locally in theComposite (line 69):
• The call toFindwill go to the appropriate method, depending on the actual type of
cat runtime This supports the Composite pattern’s ideal of havingComponents andComposites be treated the same
That completes the theoretical Composite pattern implementation Apart from theconcern with theDisplaymethod, the three preceding types can be used together forany elements Thus, we can put them in a namespace calledCompositePatternfor use
in the next example.Example: Photo Library
In this example, we are concerned with collecting the filenames of digital photos intonamed sets We will not use actual images in this example, just filenames as strings.The client is given a domain-specific set of commands with which to create andmanipulate the library Central to the manipulation of the library, from the user’spoint of view, is “where we are.” We start out at an empty set called “Album.” Some
Trang 16Composite Pattern | 57
of the commands leave the system at the component that has just been adjusted,whereas others move it back to the first component in the set The commands are:AddSet
Add a new empty set with a name and stay there
Exit the program
Thus, the two operations that work on eitherComponents orComposites areFindandRemove Consider some examples of the workings of this system, illustrated inExample 3-2 The input commands are shown in the middle, the result ofDisplayisshown on the left, and some commentary appears on the right
The input file contains all the commands in the middle The program
will expect this file to be called Composite.dat.
Example 3-2 Composite pattern—Photo Library sample run
Display Returns to start of Album
Set Album length :2
Set Home length :2