锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
鎬葷粨錛?a href="http://m.shnenglu.com/mzty/archive/2007/08/13/29922.html">
http://m.shnenglu.com/mzty/archive/2007/08/13/29922.html C++楂樼駭
http://m.shnenglu.com/mzty/archive/2007/03/02/19109.html C++鍩虹
http://m.shnenglu.com/mzty/archive/2007/04/16/22064.html C#鐣岄潰錛孋++鏍稿績綆楁硶
http://m.shnenglu.com/mzty/archive/2007/03/04/19163.html 璁捐妯″紡
http://m.shnenglu.com/mzty/archive/2007/03/29/20893.html 64bit錛孎W3.0闅忕瑪鍒嗙被
http://m.shnenglu.com/mzty/archive/2007/03/29/20892.html windows鑴氭湰鎶鏈?/p>
http://m.shnenglu.com/mzty/archive/2007/03/04/19167.html C#鍩虹
//policy妯″紡鐨勫父瑙佷嬌鐢ㄥ疄渚媠martptr錛?/span>
template
<
class T,
template <class> class CheckingPolicy,
template <class> class ThreadingModel
>
class SmartPtr
: public CheckingPolicy<T>
, public ThreadingModel<SmartPtr>

{
T* operator->()
{
typename ThreadingModel<SmartPtr>::Lock guard(*this);
CheckingPolicy<T>::Check(pointee_);
return pointee_;
}
private:
T* pointee_;
};
template <class T>
struct OpNewCreator

{
static T* Create()
{
return new T;
}
};
template <class T>
struct MallocCreator

{
static T* Create()
{
void* buf = std::malloc(sizeof(T));
if (!buf) return 0;
return new(buf) T;
}
};
template <class T>
struct PrototypeCreator

{
PrototypeCreator(T* pObj = 0)
:pPrototype_(pObj)
{}
T* Create()
{
return pPrototype_ ? pPrototype_->Clone() : 0;
}
T* GetPrototype()
{ return pPrototype_; }
void SetPrototype(T* pObj)
{ pPrototype_ = pObj; }
private:
T* pPrototype_;
};
//test class
class Widget

{
};
//璋冪敤鏂規硶涓錛?/span>
template <class CreationPolicy>
class WidgetManager : public CreationPolicy

{
};
void main()

{
typedef WidgetManager< OpNewCreator<Widget> > MyWidgetMgr;

}
//璋冪敤鏂規硶浜岋細鍥犱負涓鑸琈anager鏄壒瀹氫簬鏌愪竴綾葷殑class錛屾墍浠ュ湪Manager涓氨鎸囧畾瑕佸鐞嗙殑class綾誨瀷銆?/span>
template <template <class Created> class CreationPolicy>
class WidgetManager : public CreationPolicy<Widget>

{
};
void main()

{
// Application code
typedef WidgetManager<OpNewCreator> MyWidgetMgr;
}
template <class T>
struct OpNewCreator

{
static T* Create()
{
return new T;
}
protected:
~OpNewCreator()
{}
};
template <template <class> class CreationPolicy>
class WidgetManager : public CreationPolicy<Widget>

{
void SwitchPrototype(Widget* pNewPrototype)
{
CreationPolicy<Widget>& myPolicy = *this;
delete myPolicy.GetPrototype();
myPolicy.SetPrototype(pNewPrototype);
}
};First step in any MFC application is the creation of application object (object of class derived from CWinApp). There should be only one application object in an instance of MFC application. CWinApp is designed to make sure that only application object is present in a given instance. CWinApp and its descendants are called Singleton Classes. A class (CWinApp or its descendant) that assures a maximum of ONE object of its type at a given time and provides a global access point (AfxGetApp() method) to this object is a Singleton class.
As this principle is applied over and over again to solve recurring object "creational" problems, this becomes a pattern. Singleton Pattern ensures that a class only has one instance and provides a global access point it. The article Creating Singleton Objects using Visual C++ talks about different approaches for implementing Singletons.
Bridge Pattern is all about decoupling an abstraction (interface) from its implementation so that the two can vary independently. In MFC, the process of storing/retrieving an object to/from a persistence mechanism (like a file) is called Serialization. MFC uses the Bridge Pattern to implement Serialization. CArchive and CFile classes implement object Serialization. CArchive class provides the interface for writing/reading an object to/from a persistence mechanism whereas the CFile and its sub classes provides implementation for different persistence mechanisms such as memory, disk file, sockets etc.
A CArchive object is configured with an object of class CFile (or a derived class) during its construction, from which it obtains the necessary information for serialization, including the filename and type of the requested operation (a read or write). Client performing the Serialization operation can use CArchive object without regarding the persistence mechanism implemented by CFile classes.
The article Bridge Pattern - Bridging the gap between Interface and Implementation talks about Bridge pattern in detail.
The Observer Pattern is intended to "Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically". An object that is subjected to change is called a Subject and an object that depends on the Subject's state is called an Observer.
MFC uses a Document/View variant of the Observer Pattern. MFC's famous Document/View architecture uses this variant. A document contains the data object and acts as a Subject. A view is a window object through which the user updates the document and it acts as an Observer. A document can have multiple views. Whenever the data in the document is changed by one of the views, it updates the document by calling UpdateAllViews method, with optional hint about the modification. To inform about the change to other views, the document object calls OnUpdate method for each view attached to it (except the view that called UpdateAllViews). Derived view classes can override the OnUpdate method and update themselves by querying the data from the document.
The article Applying Observer Pattern in C++ Applications talks about Observer pattern in detail.
Design Pattern provides a common language for designers and helps them to decompose systems into a set of cooperating classes and objects. They provide proven design solution to recurring problems. In this article, I have introduced the design pattern and how MFC is using some of the patterns in its design. We can easily find more and more patterns when we dig into MFC and its classes.
|
// Visitor pattern -- Structural example
|
|
using System;
using System.Collections; namespace DoFactory.GangOfFour.Visitor.Structural { 聽聽 聽聽// MainApp test application 聽聽class MainApp 聽聽{ 聽聽聽聽staticvoid Main() 聽聽聽聽{ 聽聽聽聽聽聽// Setup structure 聽聽聽聽聽聽ObjectStructure o = new ObjectStructure(); 聽聽聽聽聽聽o.Attach(new ConcreteElementA()); 聽聽聽聽聽聽o.Attach(new ConcreteElementB()); 聽聽聽聽聽聽// Create visitor objects 聽聽聽聽聽聽ConcreteVisitor1 v1 = new ConcreteVisitor1(); 聽聽聽聽聽聽ConcreteVisitor2 v2 = new ConcreteVisitor2(); 聽聽聽聽聽聽// Structure accepting visitors 聽聽聽聽聽聽o.Accept(v1); 聽聽聽聽聽聽o.Accept(v2); 聽聽聽聽聽聽// Wait for user 聽聽聽聽聽聽Console.Read(); 聽聽聽聽} 聽聽} 聽聽// "Visitor" 聽聽abstractclass Visitor 聽聽{ 聽聽聽聽publicabstractvoid VisitConcreteElementA( 聽聽聽聽聽聽ConcreteElementA concreteElementA); 聽聽聽聽publicabstractvoid VisitConcreteElementB( 聽聽聽聽聽聽ConcreteElementB concreteElementB); 聽聽} 聽聽// "ConcreteVisitor1" 聽聽class ConcreteVisitor1 : Visitor 聽聽{ 聽聽聽聽publicoverridevoid VisitConcreteElementA( 聽聽聽聽聽聽ConcreteElementA concreteElementA) 聽聽聽聽{ 聽聽聽聽聽聽Console.WriteLine("{0} visited by {1}", 聽聽聽聽聽聽聽聽concreteElementA.GetType().Name, this.GetType().Name); 聽聽聽聽} 聽聽聽聽publicoverridevoid VisitConcreteElementB( 聽聽聽聽聽聽ConcreteElementB concreteElementB) 聽聽聽聽{ 聽聽聽聽聽聽Console.WriteLine("{0} visited by {1}", 聽聽聽聽聽聽聽聽concreteElementB.GetType().Name, this.GetType().Name); 聽聽聽聽} 聽聽} 聽聽// "ConcreteVisitor2" 聽聽class ConcreteVisitor2 : Visitor 聽聽{ 聽聽聽聽publicoverridevoid VisitConcreteElementA( 聽聽聽聽聽聽ConcreteElementA concreteElementA) 聽聽聽聽{ 聽聽聽聽聽聽Console.WriteLine("{0} visited by {1}", 聽聽聽聽聽聽聽聽concreteElementA.GetType().Name, this.GetType().Name); 聽聽聽聽} 聽聽聽聽publicoverridevoid VisitConcreteElementB( 聽聽聽聽聽聽ConcreteElementB concreteElementB) 聽聽聽聽{ 聽聽聽聽聽聽Console.WriteLine("{0} visited by {1}", 聽聽聽聽聽聽聽聽concreteElementB.GetType().Name, this.GetType().Name); 聽聽聽聽} 聽聽} 聽聽// "Element" 聽聽abstractclass Element 聽聽{ 聽聽聽聽publicabstractvoid Accept(Visitor visitor); 聽聽} 聽聽// "ConcreteElementA" 聽聽class ConcreteElementA : Element 聽聽{ 聽聽聽聽publicoverridevoid Accept(Visitor visitor) 聽聽聽聽{ 聽聽聽聽聽聽visitor.VisitConcreteElementA(this); 聽聽聽聽} 聽聽聽聽publicvoid OperationA() 聽聽聽聽{ 聽聽聽聽} 聽聽} 聽聽// "ConcreteElementB" 聽聽class ConcreteElementB : Element 聽聽{ 聽聽聽聽publicoverridevoid Accept(Visitor visitor) 聽聽聽聽{ 聽聽聽聽聽聽visitor.VisitConcreteElementB(this); 聽聽聽聽} 聽聽聽聽publicvoid OperationB() 聽聽聽聽{ 聽聽聽聽} 聽聽} 聽聽// "ObjectStructure" 聽聽class ObjectStructure 聽聽{ 聽聽聽聽private ArrayList elements = new ArrayList(); 聽聽聽聽publicvoid Attach(Element element) 聽聽聽聽{ 聽聽聽聽聽聽elements.Add(element); 聽聽聽聽} 聽聽聽聽publicvoid Detach(Element element) 聽聽聽聽{ 聽聽聽聽聽聽elements.Remove(element); 聽聽聽聽} 聽聽聽聽publicvoid Accept(Visitor visitor) 聽聽聽聽{ 聽聽聽聽聽聽foreach (Element e in elements) 聽聽聽聽聽聽{ 聽聽聽聽聽聽聽聽e.Accept(visitor); 聽聽聽聽聽聽} 聽聽聽聽} 聽聽} } |
|
ConcreteElementA visited by ConcreteVisitor1
ConcreteElementB visited by ConcreteVisitor1 ConcreteElementA visited by ConcreteVisitor2 ConcreteElementB visited by ConcreteVisitor2 |

namespace Iterator_DesignPattern

{
using System;
using System.Collections;
class Node 
{
private string name;
public string Name 
{
get 
{
return name;
}
}
public Node(string s)
{
name = s;
}
}
class NodeCollection 
{
private ArrayList list = new ArrayList();
private int nodeMax = 0;
// left as a student exercise - implement collection
// functions to remove and edit entries also
public void AddNode(Node n)
{
list.Add(n);
nodeMax++;
}
public Node GetNode(int i)
{
return ((Node) list[i]);
}
public int NodeMax 
{
get 
{
return nodeMax;
}
}
}

/**//*
* The iterator needs to understand how to traverse the collection
* It can do that as way it pleases - forward, reverse, depth-first,
*/
abstract class Iterator 
{
abstract public Node Next();
}
class ReverseIterator : Iterator
{
private NodeCollection nodeCollection;
private int currentIndex;
public ReverseIterator (NodeCollection c)
{
nodeCollection = c;
currentIndex = c.NodeMax -1; // array index starts at 0!
}
// note: as the code stands, if the collection changes,
// the iterator needs to be restarted
override public Node Next()
{
if (currentIndex == -1)
return null;
else
return(nodeCollection.GetNode(currentIndex--));
}
}

/**//// <summary>
/// Summary description for Client.
/// </summary>
public class Client
{
public static int Main(string[] args)
{
NodeCollection c = new NodeCollection();
c.AddNode(new Node("first"));
c.AddNode(new Node("second"));
c.AddNode(new Node("third"));
// now use iterator to traverse this
ReverseIterator i = new ReverseIterator(c);
// the code below will work with any iterator type
Node n;
do 
{
n = i.Next();
if (n != null)
Console.WriteLine("{0}", n.Name);
} while (n != null);
return 0;
}
}
}

namespace Command_DesignPattern

{
using System;
abstract class Command 
{
abstract public void Execute();
protected Receiver r;
public Receiver R
{
set 
{
r = value;
}
}
}
class ConcreteCommand : Command
{
override public void Execute()
{
Console.WriteLine("Command executed");
r.InformAboutCommand();
}
}
class Receiver 
{
public void InformAboutCommand()
{
Console.WriteLine("Receiver informed about command");
}
}
class Invoker 
{
private Command command;
public void StoreCommand(Command c)
{
command = c;
}
public void ExecuteCommand()
{
command.Execute();
}
}

/**//// <summary>
/// Summary description for Client.
/// </summary>
public class Client
{
public static int Main(string[] args)
{
// Set up everything
Command c = new ConcreteCommand();
Receiver r = new Receiver();
c.R = r;
Invoker i = new Invoker();
i.StoreCommand(c);
// now let application run
// the invoker is how the command is exposed for the end-user
// (or a client) initiates the command,
// (e.g. toolbar button, menu item)
i.ExecuteCommand();
return 0;
}
}
}
namespace聽TemplateMethod_DesignPattern

{
聽聽聽聽using聽System;
聽聽聽聽class聽Algorithm聽
聽聽聽聽
{
聽聽聽聽聽聽聽聽public聽void聽DoAlgorithm()聽
聽聽聽聽聽聽聽聽
{
聽聽聽聽聽聽聽聽聽聽聽聽Console.WriteLine("In聽DoAlgorithm");
聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽聽聽聽聽聽聽聽聽//聽do聽some聽part聽of聽the聽algorithm聽here
聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽聽聽聽聽聽聽聽聽//聽step1聽goes聽here
聽聽聽聽聽聽聽聽聽聽聽聽Console.WriteLine("In聽Algorithm聽-聽DoAlgoStep1");聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽聽聽聽聽聽聽聽聽//聽.聽.聽.聽
聽聽聽聽聽聽聽聽聽聽聽聽//聽step聽2聽goes聽here
聽聽聽聽聽聽聽聽聽聽聽聽Console.WriteLine("In聽Algorithm聽-聽DoAlgoStep2");聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽聽聽聽聽聽聽聽聽//聽.聽.聽.聽
聽聽聽聽聽聽聽聽聽聽聽聽//聽Now聽call聽configurable/replacable聽part
聽聽聽聽聽聽聽聽聽聽聽聽DoAlgoStep3();
聽聽聽聽聽聽聽聽聽聽聽聽//聽step聽4聽goes聽here
聽聽聽聽聽聽聽聽聽聽聽聽Console.WriteLine("In聽Algorithm聽-聽DoAlgoStep4");聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽聽聽聽聽聽聽聽聽//聽.聽.聽.聽
聽聽聽聽聽聽聽聽聽聽聽聽//聽Now聽call聽next聽configurable聽part
聽聽聽聽聽聽聽聽聽聽聽聽DoAlgoStep5();
聽聽聽聽聽聽聽聽}
聽聽聽聽聽聽聽聽virtual聽public聽void聽DoAlgoStep3()
聽聽聽聽聽聽聽聽
{
聽聽聽聽聽聽聽聽聽聽聽聽Console.WriteLine("In聽Algorithm聽-聽DoAlgoStep3");聽聽聽聽聽聽聽聽
聽聽聽聽聽聽聽聽}
聽聽聽聽聽聽聽聽virtual聽public聽void聽DoAlgoStep5()
聽聽聽聽聽聽聽聽
{
聽聽聽聽聽聽聽聽聽聽聽聽Console.WriteLine("In聽Algorithm聽-聽DoAlgoStep5");聽聽聽聽聽聽聽聽聽聽聽聽
聽聽聽聽聽聽聽聽}
聽聽聽聽}
聽聽聽聽class聽CustomAlgorithm聽:聽Algorithm
聽聽聽聽
{
聽聽聽聽聽聽聽聽public聽override聽void聽DoAlgoStep3()
聽聽聽聽聽聽聽聽
{
聽聽聽聽聽聽聽聽聽聽聽聽Console.WriteLine("In聽CustomAlgorithm聽-聽DoAlgoStep3");
聽聽聽聽聽聽聽聽}
聽聽聽聽聽聽聽聽public聽override聽void聽DoAlgoStep5()
聽聽聽聽聽聽聽聽
{
聽聽聽聽聽聽聽聽聽聽聽聽Console.WriteLine("In聽CustomAlgorithm聽-聽DoAlgoStep5");
聽聽聽聽聽聽聽聽}
聽聽聽聽}

聽聽聽聽/**////聽<summary>
聽聽聽聽///聽聽聽聽Summary聽description聽for聽Client.
聽聽聽聽///聽</summary>
聽聽聽聽public聽class聽Client
聽聽聽聽
{
聽聽聽聽聽聽聽聽public聽static聽int聽Main(string[]聽args)
聽聽聽聽聽聽聽聽
{
聽聽聽聽聽聽聽聽聽聽聽聽CustomAlgorithm聽c聽=聽new聽CustomAlgorithm();
聽聽聽聽聽聽聽聽聽聽聽聽c.DoAlgorithm();
聽聽聽聽聽聽聽聽聽聽聽聽return聽0;
聽聽聽聽聽聽聽聽}
聽聽聽聽}
}鍑嗗涓涓娊璞$被錛屽皢閮ㄥ垎閫昏緫浠ュ叿浣撴柟娉曚互鍙婂叿浣撴瀯閫犲瓙鐨勫艦寮忓疄鐜幫紝鐒跺悗澹版槑涓浜涙娊璞℃柟娉曟潵榪嬌瀛愮被瀹炵幇鍓╀綑鐨勯昏緫銆備笉鍚岀殑瀛愮被鍙互浠ヤ笉鍚岀殑鏂瑰紡瀹炵幇榪欎簺鎶借薄鏂規硶錛屼粠鑰屽鍓╀綑鐨勯昏緫鏈変笉鍚岀殑瀹炵幇銆傝繖灝辨槸妯$増鏂規硶妯″紡鐨勭敤鎰忋?/p>
寰堝浜哄彲鑳芥病鏈夋兂鍒幫紝妯$増鏂規硶妯″紡瀹為檯涓婃槸鎵鏈夋ā寮忎腑鏈涓哄父瑙佺殑鍑犱釜妯″紡涔嬩竴錛岃屼笖寰堝浜哄彲鑳戒嬌鐢ㄨ繃妯$増鏂規硶妯″紡鑰屾病鏈夋剰璇嗗埌鑷繁宸茬粡浣跨敤浜嗚繖涓ā寮忋傛ā鐗堟柟娉曟ā寮忔槸鍩轟簬緇ф壙鐨勪唬鐮佸鐢ㄧ殑鍩烘湰鎶鏈紝妯$増鏂規硶妯″紡鐨勭粨鏋勫拰鐢ㄦ硶涔熸槸闈㈠悜瀵硅薄璁捐鐨勬牳蹇冦?/p>
妯$増鏂規硶妯″紡闇瑕佸紑鍙戞娊璞$被鍜屽叿浣撳瓙綾葷殑璁捐甯堜箣闂寸殑鍗忎綔銆備竴涓璁″笀璐熻矗緇欏嚭涓涓畻娉曠殑杞粨鍜岄鏋訛紝鍙︿竴浜涜璁″笀鍒欒礋璐g粰鍑鴻繖涓畻娉曠殑鍚勪釜閫昏緫姝ラ銆備唬琛ㄨ繖浜涘叿浣撻昏緫姝ラ鐨勬柟娉曠О鍋氬熀鏈柟娉曪紙primitive method錛夛紱鑰屽皢榪欎簺鍩烘湰娉曟柟娉曟繪眹璧鋒潵鐨勬柟娉曞彨鍋氭ā鐗堟柟娉曪紙template method錛夛紝榪欎釜璁捐妯″紡鐨勫悕瀛楀氨鏄粠姝よ屾潵銆?br />聽妯$増鏂規硶妯″紡涓殑鏂規硶
妯$増鏂規硶涓殑鏂規硶鍙互鍒嗕負涓ゅぇ綾伙細妯$増鏂規硶錛圱emplate Method錛夊拰鍩烘湰鏂規硶錛圥rimitive Method)銆?/p>
妯$増鏂規硶
涓涓ā鐗堟柟娉曟槸瀹氫箟鍦ㄦ娊璞$被涓殑錛屾妸鍩烘湰鎿嶄綔鏂規硶緇勫悎鍦ㄤ竴璧峰艦鎴愪竴涓葷畻娉曟垨涓涓昏涓虹殑鏂規硶銆傝繖涓ā鐗堟柟娉曚竴鑸細鍦ㄦ娊璞$被涓畾涔夛紝騫剁敱瀛愮被涓嶅姞浠ヤ慨鏀瑰湴瀹屽叏緇ф壙涓嬫潵銆?/p>
鍩烘湰鏂規硶
鍩烘湰鏂規硶鍙堝彲浠ュ垎涓轟笁縐嶏細鎶借薄鏂規硶錛圓bstract Method錛夈佸叿浣撴柟娉曪紙Concrete Method錛夊拰閽╁瓙鏂規硶錛圚ook Method錛夈?/p>
鎶借薄鏂規硶錛氫竴涓娊璞℃柟娉曠敱鎶借薄綾誨0鏄庯紝鐢卞叿浣撳瓙綾誨疄鐜般傚湪C#璇█閲屼竴涓娊璞℃柟娉曚互abstract鍏抽敭瀛楁爣紺哄嚭鏉ャ?/p>
鍏蜂綋鏂規硶錛氫竴涓叿浣撴柟娉曠敱鎶借薄綾誨0鏄庡茍瀹炵幇錛岃屽瓙綾誨茍涓嶅疄鐜版垨緗崲銆傚湪C#璇█閲岄潰錛屼竴涓叿浣撴柟娉曟病鏈塧bstract鍏抽敭瀛椼?/p>
閽╁瓙鏂規硶錛氫竴涓挬瀛愭柟娉曠敱鎶借薄綾誨0鏄庡茍瀹炵幇錛岃屽瓙綾諱細鍔犱互鎵╁睍銆傞氬父鎶借薄綾葷粰鍑虹殑瀹炵幇鏄竴涓┖瀹炵幇錛屼綔涓烘柟娉曠殑榛樿瀹炵幇銆傦紙Visual FoxPro涓」鐩悜瀵煎緩绔嬬殑欏圭洰浼氫嬌鐢ㄤ竴涓狝ppHook綾誨疄鐜扮洃瑙嗛」鐩垚鍛樺彉鍖栵紝璋冩暣緋葷粺緇撴瀯鐨勫伐浣溿傦級閽╁瓙鏂規硶鐨勫悕瀛楅氬父浠o寮濮嬨?/p>

namespace Bridge_DesignPattern

{
using System;
class Abstraction 
{
protected Implementation impToUse;
public void SetImplementation(Implementation i)
{
impToUse = i;
}
virtual public void DumpString(string str)
{
impToUse.DoStringOp(str);
}
}
class DerivedAbstraction_One : Abstraction 
{
override public void DumpString(string str)
{
str += ".com";
impToUse.DoStringOp(str);
}
}
class Implementation 
{
public virtual void DoStringOp(string str)
{
Console.WriteLine("Standard implementation - print string as is");
Console.WriteLine("string = {0}", str);
}
}
class DerivedImplementation_One : Implementation 
{
override public void DoStringOp(string str)
{
Console.WriteLine("DerivedImplementation_One - don't print string");
}
}
class DerivedImplementation_Two : Implementation 
{
override public void DoStringOp(string str)
{
Console.WriteLine("DerivedImplementation_Two - print string twice");
Console.WriteLine("string = {0}", str);
Console.WriteLine("string = {0}", str);
}
}

/**//// <summary>
/// Summary description for Client.
/// </summary>
public class Client
{
Abstraction SetupMyParticularAbstraction() 
{
// we localize to this method the decision which abstraction and
// which implementation to use. These need to be decided
// somewhere and we do it here. All teh rest of the client
// code can work against the abstraction object.
Abstraction a = new DerivedAbstraction_One();
a.SetImplementation(new DerivedImplementation_Two());
return a;
}
public static int Main(string[] args)
{
Client c = new Client();
Abstraction a = c.SetupMyParticularAbstraction();
// From here on client code thinks it is talking to the
// abstraction, and will not need to be changed as
// derived abstractions are changed. 
// more client code using the abstraction goes here
// . . .
a.DumpString("Clipcode");
return 0;
}
}
}