More runtime flexibility and future proofing; GOF Structural Patterns with C# - by Barry Mossman

By: Barry Mossman

Abstract: This is the second article in a series upon the GOF Design patterns from a C# and .Net Framework perspective. It examines the STRUCTURAL Patterns. It focuses upon the benefits that would be obtained from their use. Reworked 5th August 2004.

by BarryMossman<is_at>primos.com.au

(5th August 2004: article and demostration program reworked to remove heavy use of Interface declarations as I have since learnt that these are not recommded in most situations)

This is my second article about the GOF Design patterns. The first article studied the Creational Patterns, while this one looks at the Structural Patterns. The first article also gave an overview of where the patterns came from, and the general discussion of the general techniques that they promoted. There is a link to my first article at the bottom of this one, but I will firstly briefly recap a few of the points from that article.

The source for this article's demonstration program is available at CodeCentral. See link at the bottom of this document. The program contains annotated example displays, and also displays some notes about the patterns, so if you are interested in starting to work with the patterns it may be a useful utility to have on your desktop during the learning period.

The GOF design patterns help address the following challenges :

  • design ready to accommodate change & growth
  • design flexible systems that come ready to handle reconfiguration and run time tailoring
  • code in manner to facilitate reuse during the development and extension phases ... ie. both external and internal reuse, so that we are rewarded by efficiencies as the project progresses, coming for investments made earlier in the project.
  • implement change in a way that doesn't overly shorten the system's useful lifespan

In a multi-person project the design patterns have the additional utility of providing a shorthand language with which to describe design options and specifications.

The design patterns were defined in the programming classic entitled "Design Patterns" by Gamma, Helm, Johnson & Vlissides. The four authors are commonly described as the Gang Of Four (GOF) for brevity. The subtitle of the book is "elements of reusable object-oriented software".

The GOF described various categories of patterns:

  • Creational Patterns
  • Structural Patterns <===== covered by this article
  • Behavioral Patterns

One of the book's key points is that the authors favour using "object composition" over "class inheritance" when designing our system's objects. This means that our objects are assembled at runtime from a number of helper classes working together to deliver the desired behaviour, rather than being statically defined at compile time using class inheritance. Objects that are created in this favoured way offer a great deal of runtime flexibility, and are better set up for future modification. A general theme of the design patterns is that they allow the composition of larger and more flexible structures from smaller helper classes.

The approach necessitates more physical classes, but is made more workable where the patterns are used as they help to bring an understandable structure to the design. The fact that the patterns are based upon system design structures that have been tested and refined over time is also of assistance.

Note that the advice is to only to "favour" object composition over class inheritance, not to stop using inheritance altogether. The two techniques work well together.

A summary of the patterns

Pattern Name

General Objective

Adapter

Allows us to provide a new interface for a class that already exists, allowing reuse of a heritage class where our client requires a different interface.

Also allows us to build a new class which will have "pluggable" adapters tailored for individual client needs.

Bridge

Allows us to decouple a class from it's interface.

This allows the class and it's interface to be changed independently over time which can lead to more reuse and less future shock.

It also allows us to dynamically switch between implementations at runtime allowing increased levels of runtime flexibility.

Composite

A flexible pattern that allows the client to deal with complex and flexible tree structures.

The trees can be built from various types of containers or leaf nodes, and it's depth or composition can be adjusted or determined at runtime.

The client is simplified as it can deal with the tree as a single object, as the Composite pattern can take care of dealing appropriately with all the differing component parts.

Decorator

Allows us to dynamically modify an object at runtime by attaching new behaviours, or by modifying existing ones.

Is applied just to specific object instances rather than to the class as a whole.

Can allow design of "pay as you go" systems where overhead is incurred only when runtime, or configuration options, require it.

Is best limited to changing an object's "skin" rather than it's "guts".

Facade

This pattern allows us to simplify the client by creating a simplified interface into a subsystem, or by creating a unified interface into a group of subsystems.

Potential benefits are to simplify the client, compartmentalise the client, help future proof our application, or enable more reuse.

Flyweight

This pattern optimises memory use when we need a design a class with which our client will want to create a very large number runtime of objects.

The pattern is most applicable if there will be clusters of runtime objects that have similar state (data), as it arranges sharing of these instances.

The pattern works well with the Composite pattern.

Proxy

This pattern provides a surrogate object that controls access to some other object.

The aim is to simplify the client when it needs to use an object that has complications.

Examples include objects upon a remote system, objects who have client authentication requirements, or objects that are expensive to fully create so some client purposes may be served with just a cut down instantiation.

Adapter Pattern

This pattern allows us to define a different interface for a class that already exists. The pattern is also known as a "wrapper".

The class that the client interacts with is called the "adapter" class, and the class, behind the scenes, that they are actually using is called the "adaptee" class.

Reasons that we may wish to use the Adapter pattern could be:

  • We wish to use an existing "heritage" class or external tool set, but our client requires a different interface to that which is currently exposed.
  • Or we are building a new class that we expect will be much reused. It may be easier for these future clients if we minimise any assumptions about the interface that they will wish to deploy when using our class. We have the option of building interface adaption into our class; this is called a "pluggable adapter". We could design the adaptee class interface to be very detailed. We could then design one or more adapter classes where the interface of each is more simple and is tailored to the specific business need of it's particular set of clients.

There are two implementation approaches for the Adapter pattern:

  • CLASS Adapter: our adaptee inherits from the adapter, providing the new interface
    • an advantage is that it will probably be the most efficient of the two approaches
  • OBJECT Adapter: our adaptee is :does not descend from the adapter, but instead it creates a private instance, and then uses that instance to service the client's requests
    • an advantage is that the one adapter can work with multiple adaptees, so is preferable if the adaptee has subclasses
    • another advantage is that the adapter can expose just the interface that is required by the client.

My illustration program demonstrates both Object and Class Adapters.

Firstly let us look at the client code that is using the Adapter pattern. The following code shows the client first using the older Adapatee class, and then using the Adapter with it's new interface. The heritage object's interface exposes method calls, while the new look uses properties.

        // use the "heritage" object
        ShowUserCommentary(1);
        ConcreteAdaptee adaptee = new ConcreteAdaptee();
        listBox1.AppendText(adaptee.SayWho());
        listBox1.AppendText(String.Format("nMade on {0}n", adaptee.SayWhen()));

        // use the heritage object with a new interface via an Object Adapter
        ShowUserCommentary(2);
        ObjectAdapter adapter = new ObjectAdapter();
        listBox1.AppendText(adapter.Name);
        listBox1.AppendText(String.Format("nMade on a {0} in {1}n",
                adapter.DayOfWeek, adapter.Month));

The output is as follows (The "UserCommentary" is in black, and the "AppendText" output is in blue):




The heritage (Adpatee) class was defined as follows:

       // ------------ "heritage" class
        public class ConcreteAdaptee {
                public string SayWho() {
                        return this.ToString();
                }
                public string SayWhen() {
                        return System.DateTime.Now.ToShortDateString();
                }
        }

As mentioned above there are two implementation approaches for the Adapter pattern. The first is the OBJECT adapter where we create a private instance of the Adaptee inside the adapter, and then translate from the new interface into the old interface to achieve the client's wishes. This approach is useful when we are providing an Adapter to be used with a family of Adaptees as we can choose at runtime which Adaptee class to instantiate privately. This means that we have to provide just the one Adapter for use with all Adaptees.

        /*----------- Approach #1: OBJECT Adapter 

--------------*/
        public class ObjectAdapter {
                // fields
                private ConcreteAdaptee _concreteAdaptee = new ConcreteAdaptee();
                // properties
                public string Name {
                        get {
                                return _concreteAdaptee.SayWho();
                        }
                }
                public string DayOfWeek {
                        get {
                                DateTime dt = System.DateTime.Parse(_concreteAdaptee.SayWhen());
                                return (dt.DayOfWeek.ToString());
                        }
                }
                public string Month {
                        get {
                                DateTime dt = System.DateTime.Parse(_concreteAdaptee.SayWhen());
                                return CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[dt.Month-1];
                        }
                }
        }

The other Adapter pattern implementation is a Class Adapter where we inherit the Adapter from the Adaptee's class. This is more efficient as the client will work directly with an object, rather than the Adapter needing to create it's hidden private object and doing double handling translation behind the scenes.

        /*----------- Approach #2: CLASS Adapter 

--------------*/
        public class ClassAdapter: ConcreteAdaptee{
                // properties
                public string Name {
                        get {
                                return base.SayWho();
                        }
                }
                public string DayOfWeek {
                        get {
                                DateTime dt = System.DateTime.Parse(base.SayWhen());
                                return (dt.DayOfWeek.ToString());
                        }
                }
                public string Month {
                        get {
                                DateTime dt = System.DateTime.Parse(base.SayWhen());
                                return CultureInfo.CurrentCulture.DateTimeFormat.MonthNames[dt.Month-1];
                        }
                }
        }

Bridge Pattern

This pattern allows us to decouple a class from it's interface. The pattern is also known as a "handle". The class that provides the interface is called the Abstraction, and the class that provides the service is called the Implementor. The client creates both, and then advises the Abstraction that it is to use this specific Implementor for this run.

A simple abstract class with subclassed implementations already give us similar functionality, but the implementations are permanently bound to the abstraction. The Bridge pattern allows to make changes to either the interface or the implementation independently of each other. This flexibility may become useful in the future as it helps to future proof our systems against unexpected change requirements. It will aid reuse and extension if we can vary each independently in this way. The pattern also allows us to dynamically switch implementations at runtime giving the possibility increased runtime flexibility.

Deja vu ? Doesn't this sound a bit like the Adapter pattern ?

Although the Bridge pattern is similar to the Adapter pattern, they are different in intent and timing. The Adapter pattern intent is to allow us to use an implementation via a different interface. This is normally done after the implementation has been published and is in use. The Bridge pattern intent is to allows us to use multiple implementations with possibly multiple interfaces. This is normally part of the original design of the implementation itself.

My illustration program uses the Abstraction to call an Implementor that states it's name and tells the time. It then switches to another Implementor and makes the same call again. The new Implementor states it's own name, and tells the time in a different format. Here are the client calls:

        ShowUserCommentary(1);
        ImplementorBase implementor = new ConcreteImplementorA();
        ConcreteAbstraction abstraction = new ConcreteAbstraction();
        abstraction.Implementor = implementor;
        listBox1.AppendText(abstraction.SayWho());
        listBox1.AppendText(String.Format("n{0}", abstraction.SayWhen()));

        // now access use the same calls & interface to access a different
        // Implementor
        ShowUserCommentary(2);
        implementor = new ConcreteImplementorB();
        abstraction.Implementor = implementor;
        listBox1.AppendText(abstraction.SayWho());
        listBox1.AppendText(String.Format("n{0}", 

abstraction.SayWhen()));

Here is the output that we get:




Firstly let us look at the implementation of the Abstraction.

        // --- Concrete Abstraction
        // The interface allowing access to the Implementor.
        public class ConcreteAbstraction {
                // fields
                ImplementorBase _Implementor;
                // properties
                public ImplementorBase Implementor {
                        set {
                                _Implementor = value;
                        }
                }
                // methods
                public string SayWho() {
                        if (_Implementor == null)
                                throw new Exception("You must assign an Implementor 

before using the Abstraction.");
                        return _Implementor.GetName();
                }
                public string SayWhen() { 
                        if (_Implementor == null)
                                throw new Exception("You must assign an Implementor 

before using the Abstraction.");
                        return _Implementor.GetTime();
                }
        }

And finally the Implementors.

        // --- Concrete Implementations
        // No public memebers. The client should only access methods via an
        // Abstraction instance.
        abstract public class ImplementorBase {
                // methods
                internal string GetName() {
                        return this.ToString();
                }
                internal abstract string GetTime() ;
        }

        public class ConcreteImplementorA: ImplementorBase {
                // methods
                override internal string GetTime() {
                        return System.DateTime.Now.ToString();
                }
        }

        // A different implementation of the same services
        public class ConcreteImplementorB: ImplementorBase {
                // fields
                private readonly DateTime _CSharpBLaunch = new System.DateTime(2003,5,6);
                // methods
                override internal string GetTime() {
                        return String.Format("{0} days since C#B launch",
                                System.DateTime.Now.Subtract(_CSharpBLaunch).Days.ToString());
                }
        }

Composite Pattern

This pattern allows us our client to work with complex and dynamic tree structure objects.

The tree is built from two families of object. One family are containers (Composites), and the other family are terminal nodes (Leaves). Any Composite, at any level in the tree, can contain Leaves or further Composites, so the tree structure can be of any depth. The tree's structure can be determined, or altered, at run time making this a very powerful and flexible pattern.

A focus of the pattern is to simplify the client by allowing it operate, with generic code, upon the whole tree, a branch from the tree, or just a single leaf. The use of this pattern will simplify the client as it is working with tree objects generically regardless of whether the object is a composite which in turn contains objects, an empty composite, or just a terminal leaf node. We avoid a dense set of switch blocks from having to be littered throughout our client.

The pattern will also future proof the client somewhat as it will not be impacted if we add further types of composite or leaves to build the tree from. It is working with these objects generically and did not know which concrete classes it was dealing with anyway.

The pattern's above objective relies upon the fact that we can design a common interface for both Composites & Leaves. There are two conflicting design considerations:

  • we want to be able handle Composites and Leaves generically for the above reasons

  • the danger is that if the common interface, for example, contains members that are only appropriate for Composites, then we .run the danger of client code making an inappropriate call against a Leaf object.

We can handle this inside the Leaf by having a null implementation, but this may just hide a client bug. We want to employ strong typing to avoid such bugs in the first place. If, for example, there is a separate Composite interface, and the Composite-only members are defined down the inheritance chain away from the Leaves we will have better safety. The cost of course is that our client has become more complex as it needs to test which form of object it is dealing with.

The answer is to put as much functionality as possible into their common ancestor, providing separate implementations via member overrides. It helps if we consider a Leaf to be just a permanently empty Composite. For the remaining members where safety is required we move to Plan B. My demonstration program illustrates these issues.

There is a further illustration of the composite pattern within the Flyweight pattern's demonstration as these patterns can work well together.

This first illustration of the composite pattern has a tree structure which is built from two types of composite, and two types of Leaf. Either composite type can contain either leaf type.

Firstly our client builds a multi-level tree, and then asks the tree to document itself via the SayWho method. This method is supported at both the composite or leaf levels. The tree as a whole is just another Composite and therefor accepts the SayWho method also.

The SayWho behaviour at each level is to print it's class name, and to indicate semi-graphically it's depth within the tree. When the SayWho method is called against a Composite, it in turn calls SayWho against each object which it contains. This behaviour recurses through the whole tree which demonstrates the powerful utility of the pattern. Here is the client code:

        // Create a "tree" structure
        ComponentBase tree = new ConcreteContainer1();
        tree.Add(new ConcreteLeaf1());
        ComponentBase container = new ConcreteContainer2();
        ComponentBase container2 = new ConcreteContainer2();
        container2.Add(new ConcreteLeaf2());
        container2.Add( new ConcreteLeaf1());
        container.Add(container2);
        container.Add( new ConcreteLeaf1());
        tree.Add(container);
        ComponentBase leaf = new ConcreteLeaf1();
        tree.Add(leaf);

        // The SayWho method processes the tree as a whole. It returns a
        // string that portrays the structure semi-graphically.
        ShowUserCommentary(1);
        listBox1.AppendText(tree.SayWho());

This produces the following output:




The client then steps through the lower level of the tree to reinforce the idea that the method can work with either Composites or Leaves. Again the call against a Composite causes the whole structure to be documented:

        // Now step through the 1st level of the tree. The same 

method is
        // working with both Composites or Leaves.
        ShowUserCommentary(2);
        foreach (ComponentBase obj in tree) {
                listBox1.SelectionColor = System.Drawing.Color.MediumBlue;
                listBox1.AppendText(obj.SayWho());
                listBox1.AppendText("------------n");
        }

This produces output as follows:




The client then demonstrates further capabilities of the Composite pattern. It firstly jumps to a specific tree position rather than navigating forward a node at a time. It then performs a method which requires the tree to process itself in a reverse direction.

        /* Position to a specific position within the structure; 

the 1st
           child of the root's 2nd child. ie. we will be 3 deep in the
           structure. This demonstrates the use of an indexer into the tree */
        ComponentBase node = tree[1][0];
        listBox1.AppendText(node.SayWho());
        listBox1.SelectionColor = System.Drawing.Color.MediumBlue;
        /* the following call demonstrates a call that works backwards
           through the tree */
        listBox1.AppendText(String.Format("The above object is {0} deep in the tree"
                ,(node.GetDepth()).ToString()));




Finally the client demonstrates how to handle any essential differences between the composite & leaf node's interfaces.

        /* Demonstrate how to handle any essential differences in 

composite
        & leaf interfaces. It makes no sense to try and delete an object
        from with a Leaf node. If the node object is a Composite delete
        it's child object. Remember that we are positioned within the tree */
        ShowUserCommentary(4);
        if (node is ContainerBase) {
                ComponentBase objToDelete = node[0];
                if (objToDelete != null) {
                        listBox1.AppendText(System.String.Format("Deleting 

{0}n",objToDelete.ToString()));
                        ((ContainerBase)node).Remove(objToDelete);
                        listBox1.SelectionColor = System.Drawing.Color.MediumBlue;
                        listBox1.AppendText(node.SayWho());
                }
        }




Enough talk ? Firstly we build an Abstract ancestor class for both Composite and Leaf classes. This will contain logic and fields common to both. This "graphical" illustration of the depth of the object within the tree is maintained in the _indicateNesting field. The IncreaseIndent method is called to increment the object's depth whenever it is added into a container. This behaviour recurses whenever a container is added inside an outer container. The GetDepth method illustrates backwards navigation through the tree using an object's reference to it's parent.

        // --- Abstract Class
        abstract public class ComponentBase {
                // fields
                private string _indicateNesting = "==";
                private ComponentBase _parent = null;
                // properties
                abstract public ComponentBase this[int index] {get;}

                internal ComponentBase Parent {
                        get {return _parent;}
                        set {_parent = value;}
                }
                internal string Indentation {
                        get {return _indicateNesting;}
                        set {_indicateNesting = value;}
                }
                // methods
                // Add an object into this container (if this is a container)
                abstract public void Add(ComponentBase aComponent);

                // Increment the graphical indication this object's depth within the 

tree
                virtual internal void IncreaseIndent(bool Recurse) {
                        this.Indentation += "==";
                }

                // Calculate this object's depth within the tree.
                public int GetDepth() {
                        ComponentBase work = this;
                        int i = 1;
                        while ((work.Parent != null) & (i < 99)) {
                                i++;
                                work = work.Parent;
                        }
                        return i;
                }

                // Provide an enumerator to drive "foreach"
                virtual public IEnumerator GetEnumerator() { return null; }

                // Build a string that semi-graphical shows this objects structure
                // This method is overriden for the container classes
                virtual public string SayWho() {
                        return (System.String.Format("{0}> 

{1}n",this.Indentation,this.ToString()));
                }
        }

Next we have the implementation of the Composite classes.

        // --- Container Classes
        abstract public class ContainerBase: ComponentBase {
                // Fields
                private ArrayList ChildContents = new ArrayList();
                // Properties
                override public ComponentBase this[int index] {
                        get {
                                if (index >= ChildContents.Count)
                                        throw new ArgumentException("No such 

child");
                                        return (ComponentBase)ChildContents[index];
                                }
                        }
                        // Methods
                        override public void Add(ComponentBase aComponent) {
                                ComponentBase newChild = (ComponentBase)aComponent;
                                newChild.Parent = this;
                                newChild.IncreaseIndent(false);
                                ChildContents.Add(aComponent);
                        }

                        override public IEnumerator GetEnumerator() {
                                return ChildContents.GetEnumerator();
                        }

                        override internal void IncreaseIndent(bool Recurse) {
                                foreach (ComponentBase xx in ChildContents) {
                                        // if this is another container handle all it's children 

too
                                        if (xx is ContainerBase) {
                                                ((ContainerBase)xx).IncreaseIndent(true);
                                        }
                                        xx.Indentation += "==";
                                }
                                // only handle our own indentation once
                                if (!Recurse)
                                        this.Indentation += "==";
                        }

                        // Removes an object into this Container. 
                        public void Remove(ComponentBase aComponent) {
                                ChildContents.Remove(aComponent);
                        }

                        override public string SayWho() {
                                string st = "";
                                foreach (ComponentBase xx in ChildContents) {
                                        st += xx.SayWho();
                                }
                                return (base.SayWho() + st);
                        }
                }

                public class ConcreteContainer1: ContainerBase {
                }

                public class ConcreteContainer2: ContainerBase {
                }

Finally we have the implementation of the Leaf classes. There is very little to implement at this level as the Component class has the more complex behaviour, and what little there is required for the Leaves has mostly been done in the Abstract ancestor class.

        // --- Leaf Classes
        abstract public class AbstractLeaf: ComponentBase {
                // properties
                override public ComponentBase this[int index] {
                        get { return null; }
                }
                // methods
                override public void Add(ComponentBase aComponent) {
                        throw new ApplicationException("Cannot ADD to LEAF 

nodes.");
                }
        }

        public class ConcreteLeaf1: AbstractLeaf {
        }

        public class ConcreteLeaf2: AbstractLeaf {
        }

I guess this looks like a lot of work, but we need to balance this by the fact that this is a very powerful and flexible pattern that will significantly simplify the client where it needs to process flexible and dynamic structures such as these trees

Decorator Pattern

This useful pattern allows us to dynamically modify an object at run time by attaching new behaviours, or by modify existing ones. The class to which we are going to add the new behaviour is called the Component, and the new behaviours are added by using various Decorators to operate upon the Component. The Decorator is a new class that is added into the system. The Component class does not need to, and will not, be aware of it's existence.

The Decorator's interfaces are compatible with the Component so we can use either to address the Component.

The pattern is applicable when designing new systems, and is also a useful option during a system modification project.

We could, of course, achieve the objective of attaching new behaviours to our Component class by inheriting sub-classes from the Component at compile time. The Decorator pattern has a number of benefits to static inheritance:

  • The new behaviours can be selectively applied at run time, rather than statically at compile time. This allows us to design flexible systems that are configurable by set up options or user selections.
  • The new behaviours can be selectively applied to just specific instances rather across the whole class to all instances.
  • The pattern allows us to both add and withdraw behaviours. If a behaviour is added by a Decorator we can remove the behaviour by just detaching the Decorator.
  • The pattern allows us to design systems that operate on a "pay as you go" basis where overhead is only incurred when and if the Decorator is employed.
  • In a system maintenance situation we may be able to implement change with less risk by using the Decorator pattern. We are able to extend or change existing behaviours, or to add new behaviours, without the Programmer necessarily having access to the Component class.
  • In a situation where there are many different Component classes, all with the same interface, we would be forced to create an equal number of sub-classes if we were to use static inheritance to implement the new behaviours. The Decorator pattern may enable us to use just one Decorator to work with all of the component classes.

Before proceeding we should make clear what the Decorator pattern is not. The GOF make a distinction between "changing the skin" of an object versus "changing it's guts". The Decorator pattern is only making changes to the Component from the outside. If more invasive changes are required it would be better to look to the Strategy pattern where the Component would outsource some of it's functionality to one of several Strategy classes.

The pattern bears a relationship to the Adapter pattern:

  • the Decorator pattern allows us to alter an objects behaviours while maintaining the same interface.
  • the Adapter pattern allows us to modify an objects interface.

My illustration program has a Component class which has the familiar SayWho method. The demonstration then adds various Decorators to modify the SayWho behaviour. It then changes the sequence which the Decorators are applied to achieve a different effect. Finally it shows how a Decorator can add new behaviour to the Component class.

The Component and Decorator clases are unlikely to share a common base class, however we need to be sure that the Decorators implement the same interface as the Component. We would also like to write generic code that can deal with both Components and Decorators. For this reason I have defined an interface called IGOFComponent that both the Component and Decorator classes implement. Since there is no common base class we need to use the Interface name, rather than a class name, in our client's variable declarations.

There is a second interface named IDecorator that is inherits from IGOFComponent and enables us to extend the Component's capabilities if required as is demonstrated in my program.

The client is coded as follows:

// show the native SayWho behaviour before decoration
ShowUserCommentary(1);
IGOFComponent component = new ConcreteComponent();
listBox1.AppendText(component.SayWho());

// now apply 1st form of decoration; convert to uppercase
ShowUserCommentary(2);
IGOFComponent decorator = new ConcreteDecorator1(component);
listBox1.AppendText(decorator.SayWho());

// now apply 2nd form of decoration on top; make a sentance
ShowUserCommentary(3);
IGOFComponent decorator2 = new ConcreteDecorator2(decorator);
listBox1.AppendText(decorator2.SayWho());

// now apply the decorator in the reverse sequence to show a
// different result; everything will be in upper case.
ShowUserCommentary(4);
decorator = new ConcreteDecorator2(component);
decorator2 = new ConcreteDecorator1(decorator);
listBox1.AppendText(decorator2.SayWho());

// now use a capability that has been added by decoration
ShowUserCommentary(5);
decorator = new ConcreteDecorator2(component);
listBox1.AppendText(((IDecorator)decorator2).SayWhen());

The output is:




The interfaces are defined as follows. Note that I have called the first interface IGOFComponent rather than the GOF's name of IComponent to avoid confusion with the .Net component of the same name. The Idecorator interface illustrates functionality that is introduced by the use of the Decorator.

// --- Interfaces
public interface IGOFComponent {
        // methods
        string SayWho();
}

public interface IDecorator: IGOFComponent {
        // methods
        string SayWhen();
}

We then implement the Component interface:

// --- Concrete Component
public class ConcreteComponent: IGOFComponent {
        // methods
        public string SayWho() {
                return this.ToString();
        }
}

We then create a abstract ancestor upon which to base the various Decorators. It is here that we implement the new SayWhen behaviour which is added to the Component object by the Decorators.

>// --- Abstract Decorator
abstract public class AbstractDecorator: IDecorator {
        // fields
        protected IGOFComponent _concreteComponent;
        // constructor
        public AbstractDecorator(IGOFComponent aComponent) {
                _concreteComponent = aComponent;
        }
        // methods
        public string SayWhen() {
                return String.Format("When = {0:f}",DateTime.Now);
        }

        abstract public string SayWho();
}

Finally we implement the Decorators.

// --- Concrete Decorators
public class ConcreteDecorator1: AbstractDecorator {
        // constructor
        public ConcreteDecorator1(IGOFComponent aComponent): base(aComponent) {
        }
        //methods
        override public string SayWho() {
                return _concreteComponent.SayWho().ToUpper();
        }
}

public class ConcreteDecorator2: AbstractDecorator {
        // constructor
        public ConcreteDecorator2(IGOFComponent aComponent): base(aComponent) {
        }
        // methods
        override public string SayWho() {
                char [] delimiter = new char[] {'.'};
                string beforeDecoration = _concreteComponent.SayWho();
                string [] split = null;
                split = beforeDecoration.Split(delimiter);
                return System.String.Format(
                   "I am from namespace {0} and my class name is {1}.",split);
        }
}

Facade Pattern

This pattern allows us to assist the client by creating a simplified interface into a subsystem, or by creating a unified interface into a group of subsystems. This can be desirable in both an initial system design, and in a system maintenance scenario.

In this pattern we design a Facade class that presents a simple interface that is suitable for our client's needs, and then we outsource into this Facade class any plumbing tasks required to obtain the services offered via the interface. This could include the selection of the actual classes that form the subsystem, their instantiation and configuration, building of parameters, calling methods, etc. The client has a simple view of the world that is consistent with it's needs, and any complexity that is associated with dealing with the servicing subsystem is isolated into one point, and away from application logic.

The subsystems that are being used are not aware of the fact that they are being called via a facade.

In an initial system design situation our motivation may be to create a system that is logically broken down into several subsystems. This will have a number of advantages:

  • it will be easier for an incoming programmer to learn and maintain the system as the system can be seen in smaller, simpler pieces, and we can deskill their task by the fact that the Facade class can be viewed as black box that provides the simple results that the client needs.
  • the facade pattern will enable us to decouple the subsystems by reducing dependencies and linkages. All communication between the client and the various subsystems will be via the Facade object. This will help us to future proof the system as changes in any one of the subsystems have a good chance of just being isolated to that single subsystem and the connecting facade class, rather than being spread through the whole application.
  • it may also improve the chances of code reuse as these decoupled subsystems will be easier to adopt than in a situation where we did not design in such decoupling from the outset. We have the option of building various facade classes, each suitable for different clients with differing types of requirement
  • if our client has to deal with an external subsystem that already exists we may be able to simplify life by designing a more appropriate interface for that subsystem. This could be useful if the native interface for the subsystem that we were dealing was made complex, from our point of view, by many options or parameter settings that were irrelevant to us. It would also be useful if there was a chance that we would completely replace the subsystems with new implementations some time in the future.
  • another situation would be if we needed a result from the cooperation of several pre-existing subsystems with inconsistent interfaces.

The GOF promote a application design that favours "object composition" over "class inheritance". I described the differences between these two approach in my earlier article that described the GOF's Creational Patterns. In summary this type of design dynamically assembles object behaviour via the interaction a number of smaller helper classes, rather than solely using static object inheritance to assemble our object's behaviours at compile time. The downside to this design option is that our application will contain more physical classes than a system that is built just using class inheritance. The use of the Facade pattern can reduce this as a issue as our client can still deal with what looks like relatively simple objects.

In a system maintenance scenario the use of the Facade pattern may allow us to extend the useful life of a subsystem whose interface has become dated or out of step with the current requirements. Maybe there are lots of options that are no longer applicable, or are still applicable but just not to our client.

The application will often need just a single instance of the Facade, so it is often used in conjunction with the Singleton pattern that was described in the above article.

My illustration program uses needs to obtain a greeting message from a group of inconsistent subsystems. It uses a facade to simplify itself so that it can obtain the greeting with a simple call.

        // The facade pattern builds us what seems a simple 

greeting message
        ShowUserCommentary(1);
        ConcreteFacade facade = new ConcreteFacade();
        listBox1.AppendText(facade.Greeting);

Here is the output:




The first code snippet is just part of my demonstration example, and is not part of the Facade pattern, but my illustration doesn't make much sense unless I show it here. This is the simulation of the subsystems that the facade is going to simplify from the client's perspective.

/* Some silly classes to simulate a complex subsystem whose 

interface that
   we want to simplify with a facade.
  1/ A class that provides us with a variable greeting message format.
  2/ A class that can provide the datetime in caller specified format
  3/ A class that can tell us our name in either upper or lower case.

  We are wanting our client to be able to get a simple timed, named greeting
  without getting into lots of details that are not relevant to this client's
  use of the sub-system.  */

// --- Enumerations
public enum GreetingStyles {Terse, Chatty};

// --- Sub-Systems Classes
public class SubSys_GreetingText {
     // methods
     public string GetText(GreetingStyles style) {
         switch(style){
            case GreetingStyles.Chatty:
                return "Hello and welcome, my name is {0} and the time is {1}";
            case GreetingStyles.Terse:
                return "{0}: {1}";
            default:
                throw new ApplicationException("Invalid style requested.");
         }
     }
}

public class SubSys_Time {
     // methods
     public string GetTime(string format) {
            string work = String.Format("{{0:{0}}}",format);
            return String.Format(work,DateTime.Now);
     }
}

public class SubSys_Who {
     // methods
     public string GetName(Object obj, bool aUpper) {
            return aUpper?obj.ToString().ToUpper():obj.ToString();
     }
}

Now back to the Facade itself. It needs to work with the above subsystems to obtain the greeting message for the client. All of the formatting options are an overkill for this client, so the facade has made this into a simple property access.

        // --- Concrete Facade
        public class ConcreteFacade {
                // fields
                private SubSys_GreetingText _greetingText;
                private SubSys_Time _greetingTime;
                private SubSys_Who _greetingName;
                // properties
                public string Greeting {
                        get {
                                /* The facade object is where we have the detailed knowledge of 

how
                                        to use the subsystems that we are proving a facade for. 

Here we
                                        assemble an outwardly simple greeting from a few classes 

with
                                        interfaces that are too complex for our simple 

requirement. */
                                string _greeting = _greetingText.GetText(GreetingStyles.Chatty);
                                string _time = _greetingTime.GetTime("f");
                                string _name = _greetingName.GetName(this,true);
                                return (String.Format(_greeting,_name,_time));
                        }
                }
                // constructors
                        public ConcreteFacade() {
                                // initialise the various subsystems that we will be 

using
                                _greetingText = new SubSys_GreetingText();
                                _greetingTime = new SubSys_Time();
                                _greetingName = new SubSys_Who();
                }
        }

Flyweight Pattern

The Flyweight pattern is designed for situations where we would like to use objects in our system design, but are concerned about doing so because a very large quantity of these objects will be required at runtime. The Flyweight pattern allows us to economically use objects in this case by automatically sharing an existing instance, rather than creating a new one, whenever the client asks to create an object where a mostly similar one is already in existence. This allows us to design a system where we achieve the benefits of an object orientated design even where it would seem that the memory cost of all the individual objects would too expensive.

Where object instances are being shared we are also obviously sharing the instance's data fields (termed "state" by the GOF). Flyweight objects have two classes of data; intrinsic data and extrinsic data. The shared data that is held within the flyweight instance's fields is the "intrinsic" data. Any data that is unique to each separate use of the instance is called "extrinsic" data, and has to be held outside of the instance somehow.

The flyweight pattern is only really applicable if most of the object's data can be made intrinsic (shared). The pattern allows the most memory saving where there is either a large quantity of intrinsic data associated with each instance, or where the actual data at runtime allows a lot of sharing to occur. The memory savings come at a cost of extra computational resources required to locate the correct instance and to pass extrinsic data back and forth.

Flyweights are not applicable if our application needs to use code such as "if (flyweightA == flyweightB)". The problem is that flyweightA and flyweightB may share the same instance behind the scenes, although the client regards them as separate objects.

The client uses a Flyweight Factory to create flyweight instances, and is not aware that reuse is occurring. It thinks that is always been given a fresh new instance, although of course it is having to somehow store the extrinsic data and then pass it into the flyweight whenever it is needed. This means that objects are a little more clumsy than normal objects, but at least the client is able to focus upon business issues without being bogged down with the plumbing involved in arranging the sharing.

There are "shared" and "unshared" flyweights. The "shared" versions are as described above. The "unshared" ones are just normal single use, single instance classes, which implement the same interface as their "shared" relations. The same Flyweight factory can build both as this will simplify life for the client. It will also help to future-proof the client as we will be able to easily change the class of the flyweights in a future version of the application by just changing the Flyweight Factory. The client will be able to operate unchanged with the new Flyweight objects as long as the new flyweights implement the old interface (see my article about the GOF Creational patterns in the links below).

The Flyweight pattern can be used within the Composite pattern allowing us to cheaply create a large number of Leaf nodes. The leaf nodes would be shared flyweights, and the containers would be unshared. There is a restriction however as the fact that the intrinsic data must be shared means that we will not be able to keep a reference pointing to it's container in each leaf node. This will restrict the navigation through the tree in an upwards direction unless we can hold the parent reference within extrinsic data.

My illustration program for the Flyweight pattern is within a Composite pattern context. I build a tree where the root is a document. It can contain sentences which are themselves containers. The sentences contain words and punctuation, which are the leaf nodes and are implemented as shared flyweights. The illustration seeks to show the use of both shared & unshared flyweights, also intrinsic & extrinsic data.

The tree is built from some sentences extracted from a Borland press release. Each word or piece of punctuation, is created as a shared flyweight object and is added into it's particular sentance container. The leaf object is then asked whether it seems to close the sentence. If so the sentence container is added into the document, and a new sentence container is created as an unshared flyweight object. The "intelligence" as to whether the leaf seems to close the sentence is outsourced to the leaf object, and is intended to demonstrate the kind of benefit that we are achieving from the leaf being an object. The client is fairly simple and clear due in part to the benefits coming from the Flyweight pattern and OO.

// Create Flyweight factory, and then unshared flyweight 

containers
// for the whole document and the 1st sentence.
FlyweightFactory factory = new FlyweightFactory();
IGOFComponent document = factory.CreateDocument();
IGOFComponent sentence = factory.CreateSentence();
IGOFComponent word;

ShowUserCommentary(1);

// Load the document's text from disk, and then break it up into
// a collection of individual words & punctuation.
MatchCollection itemList =  LoadAndBreakUpUnformatedDocument();
// Process each item in the collection. Create a Flyweight object
// for the item, and add it into it's sentence container. Create new
// sentances as required. The flyweight objects have a property which
// indicates whether this object closes the current sentance. This OO
// working for us as this simplifies the client.
foreach (Match m in itemList) {
        if (m.Length > 0) {
                word = factory.CreateWord(m.ToString());
                sentence.Add(word);
                if (word.IsASentenceCloser) {
                        document.Add(sentence);
                        sentence = factory.CreateSentence();
                }
        }
}

Let us ignore the LoadAndBreakUpUnformatedDocument() call1 for the moment as it is not related to the Flyweight pattern.

We are creating and using shared flyweight objects here, but the client is not aware of this optimisation. It remains simple thanks to the flyweight pattern.

The tree has been built from unformatted data. Once it has been built this demonstration then instructs the flyweight instance that contains the word "Borland" that it is to be coloured red if it is to be written. This is achieved via intrinsic data stored in the specific single instance that contains the word "Borland". It affects all uses of the word "Borland" within the tree as they all refer to the same shared instance.

The tree is then instructed to Write itself. The Composite pattern works with the Flyweight containers & leaf nodes to print the tree's data. The Write behaviour of the flyweight leaf node is to underline the word if it appears within a glossary list known to the flyweight class. This again demonstrates intrinsic data and the type of client benefit to be obtained by the words being objects. The leaf node's Write behaviour also causes the 1st word of each sentence to be bolded. This demonstrates the use of extrinsic data. Each individual use of a word shares the same single flyweight instance. The word's text is the same and is shared, but each use may have it's own individual position within it's own sentence. The sentence position is stored externally to the flyweight, and is passed extrinsic data at Write time with the above formatting behaviours.

Here is the client code that formats the word Borland, and then causes the document to print itself. Again the client has been made simple by OO.

// cause the word "Borland" to be written with a red font; 

to
// demonstrate the the incidents are shared flyweights, and to show
// use of intrinsic data.
word = factory.CreateWord("Borland");
word.colour = System.Drawing.Color.Red;

// Cause the document to write. The leaf node object's Write
// behaviour demonstrates the benefits being obtained by the fact
// that the words are objects, and illustrates the use of intrinsic
// & extrinsic state.
document.Write(listBox1,1);

Now lets us look at the output achieved. Remember that the input to this was plain unformatted text.




Now remember that my illustration of the Flyweight is within the context of a Composite pattern, so we need a interface for the nodes within the Composite pattern:

// --- Interfaces
public interface IGOFComponent {
        // properties
        Color colour {set;}     // font colour: only meaningful for leaves
        bool IsOnlyPunctuation {get;}  // is this a "word" or is it only
                                       // punctuation; only meaningful for
                                       // leaves
        bool IsASentenceCloser {get;}  // does this leaf indicate the end of 

the
                                       // the end of the sentence; only
                                       // meaningful for leaves
        //methods
        void Add(IGOFComponent aComponent);     // only meaningful for
                                                // containers
        void Write(System.Windows.Forms.RichTextBox richtextbox,
                int aPosition); // meaningful for either leaves or containers,
                                // but 2nd paramater only meaningful leaves 
                                // (it is extrinsic state 

showing the position 
                                // of the word within the sentence).
}

Next we have the FlyWeight factory. This is where the sharing occurs. The factory should only create a new instance where the object, that the client has called, for has unique intrinsic data.:

// --- Flyweight factory
/* The client uses this factory to create both the "shared" & "unshared"
   flyweight objects. The unshared ones could be created outside the factory,
   but that would make life more complex for the client.
   The method called CreateWord creates "shared" flyweights (words), and the
   other Createxxx methods create "unshared" flyweights (sentences and the
   whole document). */
public class FlyweightFactory {
        // fields
        private Hashtable Flyweights = new Hashtable();
        // methods
        public IGOFComponent CreateWord(string aWord) {
                IGOFComponent testWord = (IGOFComponent)Flyweights[aWord];
                if (testWord == null) {
                        testWord = new FlyLeaf(aWord);
                        Flyweights.Add(aWord, testWord);
                }
                return testWord;
        }
        public IGOFComponent CreateSentence() {
                return new FlySentence();
        }
        public IGOFComponent CreateDocument() {
                return new FlyDocument();
        }
}

I did not create an abstract shared ancestor for the Composite and leaf nodes, as the demonstration required no generic behaviour, and it just distracted from what I am trying to illustrate here. I have connected the two classes by having them both implement the IGOFComponent interface. So now lets us look at the implementation of the Container nodes. These are unshared Flyweights, which are really just normal classes which happen to implement the same interface as a shared Flyweight.

We can see an example of extrinsic data here. Any reuse of a an individual word will share a Flyweight instance. They share the word's text value, as well as the font colour that will be used to print the word. What they don't share is the position within the sentence for each individual use of that word. If a Flyweight operation needs such extrinsic data it needs to be passed in as a parameter. In the demonstration program the shared Flyweight's Write method needs the word's position within the sentance as it wants to bold the first word in each sentence. The extrinsic data for each context needs to be stored external to the Flyweight somehow. In this example it is inferred from the position of the reference to the shared Flyweight in it's context, ie. within the Composite's container node.

// --- Flyweight UNSHARED class: container nodes in our Composite 

pattern
abstract public class AbstractUnsharedFlyContainer: IGOFComponent {
        // fields
        private ArrayList _children = new ArrayList();
        // properties
        public Color colour {
                set {
                        throw new ApplicationException(
                                  "Colour not relevant for sentences.");
                }
        }

        public bool IsOnlyPunctuation {
                get{ return false;} // default value; overriden for 

leaves
        }

        public bool IsASentenceCloser {
                get{return true;} // default value; overriden for 

leaves
        }
        // methods
        public void Add(IGOFComponent aComponent) {
                _children.Add(aComponent);
        }
        public void Write(System.Windows.Forms.RichTextBox richtextbox,
          int aPosition) {
                int i = 1;
                /* the position of the word in the sentance is an example of
                a flyweight's extrinsic data. It is passed into the flyweight
                whenever it is needed. In this case it is needed so that the 1st
                word in each sentance can be bolded. */
                foreach (IGOFComponent leaf in _children) {
                        leaf.Write(richtextbox, i);
                        if (!leaf.IsOnlyPunctuation)
                            i ++;
                        }
                }
      }

        public class FlySentence: AbstractUnsharedFlyContainer {
        }

        public class FlyDocument: AbstractUnsharedFlyContainer {
        }

Now let us look at the shared Flyweights; the words and punctuation items within a sentence. The main things to notice is the intrinsic data which is stored in the class's fields, and the use of both intrinsic and extrinsic data within the Write method.

// --- Flyweight SHARED class: leaf nodes in our Composite 

pattern
public class FlyLeaf: IGOFComponent {
        // fields; --- can only be "intrinsic" data (see BDN article)
        private string _word;
        private Color _colour = Color.Blue;     // default
        // properties
        public Color colour {
                set {   _colour = value;}
        }

        public bool IsOnlyPunctuation {
                get{
                        //return Regex.IsMatch(@"W*",_word);   // C#B bug ? Does not 

work
                        return Regex.IsMatch(
                                     @"[!#$*()-:;,.""?]",_word);
                }
       }

        public bool IsASentenceCloser {
                get{
                /* The sentance has been broken down into words & "punctuation".
                Each punctuation item is in it's own flyweight item, except for
                quoted "sentance closers" being either a quoted period or
                exclamation mark. These come as a pair, eg either ." or !" */
                switch (_word) {                                                
                        case ".": return true;
                        case @".""": return true;
                        case "!": return true;
                        case @"!""": return true;
                        default: return false;
                  }
               }
        }

        // constructors
        public FlyLeaf(string aWord) {
                _word = aWord;
                                }
        // methods
        public void Add(IGOFComponent aComponent) {
                throw new ApplicationException("Cannot ADD to LEAF nodes.");
        }
        /* Some fairly silly formatting so that we can see some "benefit"
        coming from our object. */
        public void Write(System.Windows.Forms.RichTextBox richtextbox,
                int aPosition) {
                // save existing font colour & style
                System.Drawing.Color saveColour = richtextbox.SelectionColor;
                System.Drawing.Font saveFont = richtextbox.SelectionFont;
                System.Drawing.FontStyle saveFontStyle
                                        = richtextbox.SelectionFont.Style;

                // override colour to that specified for this word (intrinsic
                // state)
                if (saveColour != _colour) richtextbox.SelectionColor = _colour;
                // use extrinsic state; set word bold if it is the 1st word in
                // it's sentence
                System.Drawing.FontStyle newFontStyle =
                                        (aPosition ==1) 
                                         ? System.Drawing.FontStyle.Bold:
                System.Drawing.FontStyle.Regular;
                // underline any word found in the "glossary" (instrinsic 
                // state again)
                if (IsWordInGlossary(_word)) newFontStyle
                                        |= System.Drawing.FontStyle.Underline;
                // override the listbox's font's style with the above changes
                richtextbox.SelectionFont = new Font(saveFont,newFontStyle);

                // write the word to the list box
                richtextbox.AppendText(String.Format("{0} ", _word));

                // restore the listbox's font & colour attributes
                richtextbox.SelectionFont = saveFont;
                richtextbox.SelectionColor = saveColour;
        }

        /* Simulate a glossary function */
        private bool IsWordInGlossary(string aWord) {
                switch (aWord) {
                        case "Kahn":
                                return true;
                        case "Fuller":
                                return true;
                        default:
                                return false;
                }
        }
}

Finally you might like to see the LoadAndBreakUpUnformatedDocument method from the client where I loaded the Press Release text and then roughly broke it appart into it's constituent words and punctuation items. This is nothing to do with the Flyweight design pattern, but I had a bit of fun with the .Net Regex class to do this, and you may be interested. The regex facility is very powerful. You can experiment with it using the excellent free ware tool called Expresso from Ultrapico (see link at the end of this document). Regex has a Matches function which matches a supplied string against a regular expression pattern. It puts all matches into a collection object. My pattern causes the text to be roughly broken up into words, numbers, "sentence closers", and individual punctuation items.

I have one confession to make; I had to edit the press release a little to make this work. I had to deprive Mr Fuller of his middle initial as it's following fullstop caused my function to prematurely flag the termination of the sentence.

/* Obtain some data for the demonstration to work with. A section 

of a
  Borland press release is loaded from a file, and then is broken up into
  a collection of words, numbers and punctuation. */
private MatchCollection LoadAndBreakUpUnformatedDocument() {
        /* collection will contain:
          * sentance closers; fullstop, exclamation mark (quoted or unquoted)
            .+""+|!+""
          * misc punctuation
            [!#$*()-:;,.""?]
          * numbers
            d+
          * words
           w*  */
        Regex regex = new Regex(@".+""+|!+""+|[!#$*()-:;,.""?]|d+|w*",
                        RegexOptions.IgnoreCase
                        | RegexOptions.Multiline
                        | RegexOptions.IgnorePatternWhitespace
                        | RegexOptions.Compiled
                                                                                                        );
        RichTextBox rich = new RichTextBox();
        const string fileName = "Flyweight words.rtf";
        try {
                rich.LoadFile(fileName);
        }
        catch (System.IO.FileNotFoundException e) {
                throw new ApplicationException(String.Format
                                ("File "{0}" is needed by this 

demonstration; {1}",
                                fileName, e.Message));
        }
        return regex.Matches(rich.Text);
}

Proxy Pattern

The Proxy pattern's role is to provide the client with a surrogate, or gatekeeper, object that controls access to some other object. The GOF named the object that the client deals as the Proxy object, and the object that it gives us access to is called the RealSubject.

The client thinks that the Proxy is the real object, and is unaware that it is using this other, behind the scenes, object. This is achieved by the fact that the Proxy implements the RealSubject's interface.

There are various situations where we obtain advantage from using a Proxy:

  • A Remote Proxy: If the RealSubject is in a remote address space we can simplify the client if it uses a local Proxy through which to communicate with the remote object. This will simplify the client allowing it to focus on business issues rather than becoming clouded with the plumbing tasks of remoting.
  • A Virtual Proxy: If the RealSubject is expensive to build we may want to defer it's instantiation until we are completely sure that the client needs it. The Proxy can provide basic overview services to the client, and will only instantiate the full RealSubject if the client uses properties or methods that require that the full object be instantiated. Again the client has been simplified as it has no knowledge of this defered construction process.
  • A Protection Proxy: This is useful if differing clients have differing access rights to the RealSubject. The proxy simplifies the client by hiding the authentiation process.
  • A Smart Proxy: This type of proxy does some generic housekeeping before, or after, use of the RealSubject. This allows us to centralise housekeeping such as pooling or locks requred for updates.

There is some similarity to the Decorator pattern as both patterns implement the interface of some other object, and stand between it and the client. The difference is in intent. The Proxy does not allow us to add or subtract capabilities from the behind the scenes object as the Decorator does. It's intent is to provide a gatekeeper when it is inconvienet or undesirable to access the RealSubject.

My illustration program shows a Remote Proxy. The client needs to use a remote server, and has been simplified by use of the Proxy. Here is the client call using what looks just to be a normal class.

// Use a method on a remote server. The Proxy pattern simpifies 

the
// client so that it can focus upon the business issues of what the
// object does for us, rather than confusing the issue by all the
// surrounding remoting plumbing.
RemProxy proxy = new RemProxy();
listBox1.AppendText(proxy.SayWho());

We need to start the "Remote Server" before pressing the "Use Proxy" button otherwise you will get the following error message followed by an exception.




The "remote server" is part of the demonstration program that is available at CodeCentral. The RemoteInterface.dll is the interface that is shared between the client's ProxyTest class and the Remote Server which is the exe called remoteServer.




Once we run the Remote Server we will see the following




Now when we press the client's "Use Proxy" button we can see the desired result. We can see that the Remote Server has been accessed by the audit trail within the DOS box window, and we can see that the result of the SayWho call has been returned to the client for display.




The interface has been declared in it's own project so that it can be shared by the Remote server, the client, and the dll that the client uses for the demonstration.

namespace RemoteInterface
{
        public interface IRemoteInterface {
                string SayWho();
        }
}

Here is the Proxy Class. The main things to note are that the reference to the RealSubject is in the field called _server. The proxy class aranges for the remote connection, handles exceptions, and makes the request for the client.

public class RemProxy : IRemoteInterface {
   // Fields
   private IRemoteInterface _server;

   // Methods
   public string SayWho() {
      TcpChannel channel = new TcpChannel();

      string classAndServerName = "";
      try {
          ChannelServices.RegisterChannel(channel);
          if( _server == null )
              _server = (IremoteInterface)Activator.GetObject
              (typeof(IRemoteInterface),
              "tcp://localhost:8085/MyRemoteClassKnown");

          try {
              classAndServerName = _server.SayWho();
          }
          catch (System.Net.Sockets.SocketException) {
                 MessageBox.Show("You must start the supplied "remote" 

server before pressing the Proxy button. The server also runs on this computer.",
                 "Problem",MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
                 throw;
          }
      }
      finally {
          ChannelServices.UnregisterChannel(channel);
      }

      return String.Format("My name is {0}.",classAndServerName);
   }
}

For the sake of completeness here is the implementation of the RealSubject with the Remote server.

class Server {
     [STAThread]
     static void Main(string[] args) {
          TcpChannel channel = new TcpChannel(8085);
          ChannelServices.RegisterChannel(channel);

          RemotingConfiguration.RegisterWellKnownServiceType(
                              typeof(MyRemoteClassKnown), "MyRemoteClassKnown",
                              WellKnownObjectMode.Singleton);
          System.Console.WriteLine("Press <enter> to exit.");
          System.Console.ReadLine();
     }

     public class MyRemoteClassKnown: MarshalByRefObject, IRemoteInterface {
          public string SayWho() {
               System.Console.WriteLine("SayWho method has been called.");
               return this.ToString();
          }
     }
}

Conclusion

This article has examined the Structural Patterns from those described by the GOF in their book titled "Design patterns". I think that the study of their design patterns is a worthwhile thing to do. I found the following links helpful while studying the patterns myself and while preparing this article. The book itself is a good investment as it provides supplementary detail upon the problems that the patterns are trying to solve, the elements of the solution, and the consequences and trade-offs involved in using the patterns.

Look out for my next article which will look at the Behavioural patterns.

Links

Server Response from: SC3