代码改变世界

[置顶]c# 设计模式(2)结构型

2011-07-14 17:38  乱世文章  阅读(174)  评论(0编辑  收藏  举报

名称

Adapter

结构



意图

将一个类的接口转换成客户希望的另外一个接口。A d a p t e r 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

适用性

  • 你想使用一个已经存在的类,而它的接口不符合你的需求。
  • 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
  • (仅适用于对象A d a p t e r )你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

Code Example

namespace Adapter_DesignPattern
{
    using System;
 
          class FrameworkXTarget 
          {
                    virtual public void SomeRequest(int x)
                    {
                               // normal implementation of SomeRequest goes here                                          
                    }
          }
 
          class FrameworkYAdaptee
          {
                    public void QuiteADifferentRequest(string str) 
                    {
                               Console.WriteLine("QuiteADifferentRequest = {0}", str);
                    }                   
          }
 
          class OurAdapter : FrameworkXTarget
          {
                    private FrameworkYAdaptee adaptee = new FrameworkYAdaptee();
                    override public void SomeRequest(int a)
                    {
                               string b;
                               b = a.ToString();
                               adaptee.QuiteADifferentRequest(b);
                    }                   
          }
 
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        void GenericClientCode(FrameworkXTarget x)
                    {
                               // We assume this function contains client-side code that only 
                               // knows about FrameworkXTarget.
                               x.SomeRequest(4);
                               // other calls to FrameworkX go here
                               // ...
                    }
                    
                    public static int Main(string[] args)
        {
                               Client c = new Client();
            FrameworkXTarget x = new OurAdapter();
                               c.GenericClientCode(x);        
            return 0;
        }
    }
}



 

名称

Bridge

结构

意图

将抽象部分与它的实现部分分离,使它们都可以独立地变化。

适用性

  • 你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时B r i d g e 模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
  • 对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
  • (C + +)你想对客户完全隐藏抽象的实现部分。在C + +中,类的表示在类接口中是可见的。
  • 有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。R u m b a u g h 称这种类层次结构为“嵌套的普化”(nested generalizations )。
  • 你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。一个简单的例子便是C o p l i e n 的S t r i n g 类[ C o p 9 2 ],在这个类中多个对象可以共享同一个字符串表示(S t r i n g R e p )。

Code Example

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;
        }
    }
}

 

名称

Composite

结构

意图

将对象组合成树形结构以表示“部分-整体”的层次结构。C o m p o s i t e 使得用户对单个对象和组合对象的使用具有一致性。

适用性

  • 你想表示对象的部分-整体层次结构。
  • 你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

Code Example

namespace FactoryMethod_DesignPattern
{
    using System;
          using System.Collections;
 
          abstract class Component 
          {
                    protected string strName;
 
                    public Component(string name)
                    {
                               strName = name;
                    }
 
                    abstract public void Add(Component c);
          
                    public abstract void DumpContents();
                    
                    // other operations for delete, get, etc.
          }
 
          class Composite : Component
          {
                    private ArrayList ComponentList = new ArrayList();
                    
                    public Composite(string s) : base(s) {}
 
                    override public void Add(Component c)
                    {
                               ComponentList.Add(c);
                    }
 
                    public override void DumpContents()
                    {
                               // First dump the name of this composite node
                               Console.WriteLine("Node: {0}", strName);
 
                               // Then loop through children, and get then to dump their contents
                               foreach (Component c in ComponentList)
                               {
                                         c.DumpContents();
                               }
                    }
          }
 
          class Leaf : Component
          {
                    public Leaf(string s) : base(s) {}
 
                    override public void Add(Component c)
                    {
                               Console.WriteLine("Cannot add to a leaf");
                    }
 
                    public override void DumpContents()
                    {
                               Console.WriteLine("Node: {0}", strName);
                    }
          }
 
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
                    Component SetupTree()
                    {
                               // here we have to create a tree structure, 
                               // consisting of composites and leafs.  
                               Composite root = new Composite("root-composite");
                               Composite parentcomposite;
                               Composite composite;
                               Leaf leaf;
 
                               parentcomposite = root;
                               composite = new Composite("first level - first sibling - composite");
                               parentcomposite.Add(composite);
                               leaf = new Leaf("first level - second sibling - leaf");
                               parentcomposite.Add(leaf);
                               parentcomposite = composite; 
                               composite = new Composite("second level - first sibling - composite");
                               parentcomposite.Add(composite);
                               composite = new Composite("second level - second sibling - composite");
                               parentcomposite.Add(composite);
 
                               // we will leaf the second level - first sibling empty, and start 
                               // populating the second level - second sibling 
                               parentcomposite = composite; 
                               leaf = new Leaf("third level - first sibling - leaf");
                               parentcomposite.Add(leaf);
                               
                               leaf = new Leaf("third level - second sibling - leaf");
                               parentcomposite.Add(leaf);
                               composite = new Composite("third level - third sibling - composite");
                               parentcomposite.Add(composite);
 
                               return root;
                    }
 
        public static int Main(string[] args)
        {   
                    Component component;
                               Client c = new Client();
                               component = c.SetupTree();
 
                               component.DumpContents();
            return 0;
        }
    }
}

 

名称

Decorator

结构

意图

动态地给一个对象添加一些额外的职责。就增加功能来说,D e c o r a t o r 模式相比生成子类更为灵活。

适用性

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 处理那些可以撤消的职责。
  • 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

Code Example

namespace Decorator_DesignPattern
{
    using System;
 
          abstract class Component
          {
                    public abstract void Draw();             
          }
 
          class ConcreteComponent : Component
          {
                    private string strName;
                    public ConcreteComponent(string s)
                    {
                               strName = s;                             
                    }
 
                    public override void Draw()
                    {
                               Console.WriteLine("ConcreteComponent - {0}", strName);                           
                    }                   
          }
 
          abstract class Decorator : Component
          {
                    protected Component ActualComponent;
 
                    public void SetComponent(Component c)
                    {
                               ActualComponent = c;
                    }
                    public override void Draw()
                    {
                              if (ActualComponent != null)
                                         ActualComponent.Draw();                  
                    }
          }
 
          class ConcreteDecorator : Decorator 
          {
                    private string strDecoratorName;
                    public ConcreteDecorator (string str)
                    {
                               // how decoration occurs is localized inside this decorator
                               // For this demo, we simply print a decorator name
                               strDecoratorName = str; 
                    }
                    public override void Draw()
                    {
                               CustomDecoration();
                               base.Draw();
                    }
                    void CustomDecoration()
                    {
                               Console.WriteLine("In ConcreteDecorator: decoration goes here");
                               Console.WriteLine("{0}", strDecoratorName);
                    }
          }
 
          
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        Component Setup() 
                    {
                               ConcreteComponent c = new ConcreteComponent("This is the real component");
 
                               ConcreteDecorator d = new ConcreteDecorator("This is a decorator for the component");
 
                               d.SetComponent(c);
 
                               return d;
                    }
                    
                    public static int Main(string[] args)
                    {
                               Client client = new Client();
                               Component c = client.Setup();    
 
                               // The code below will work equally well with the real component, 
                               // or a decorator for the component
 
                               c.Draw();
                               
            return 0;
        }
    }
}

 

名称

Facade

结构

意图

为子系统中的一组接口提供一个一致的界面,F a c a d e 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

适用性

  • 当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。F a c a d e 可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过f a c a d e 层。
  • 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入f a c a d e 将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
  • 当你需要构建一个层次结构的子系统时,使用f a c a d e 模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过f a c a d e 进行通讯,从而简化了它们之间的依赖关系。

Code Example

namespace Facade_DesignPattern
{
          using System;
 
          class SubSystem_class1 
          {
                    public void OperationX() 
                    {
                               Console.WriteLine("SubSystem_class1.OperationX called");
                    }
          }
 
          class SubSystem_class2
          {
                    public void OperationY()
                    {
                               Console.WriteLine("SubSystem_class2.OperationY called");
                    }
          }
 
          class SubSystem_class3 
          {
                    public void OperationZ()
                    {                              
                               Console.WriteLine("SubSystem_class3.OperationZ called");
                    }         
          }
 
          class Facade 
          {
                    private SubSystem_class1 c1 = new SubSystem_class1();
                    private SubSystem_class2 c2 = new SubSystem_class2();
                    private SubSystem_class3 c3 = new SubSystem_class3();
 
                    public void OperationWrapper()
                    {
                               Console.WriteLine("The Facade OperationWrapper carries out complex decision-making");
                               Console.WriteLine("which in turn results in calls to the subsystem classes");
                               c1.OperationX();
                               if (1==1 /*some really complex decision*/)
                               {
                                         c2.OperationY();
                               }
                               // lots of complex code here . . .
                               c3.OperationZ();
                    }
                    
          }
 
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
          public static int Main(string[] args)
                    {
                               Facade facade = new Facade();
                               Console.WriteLine("Client calls the Facade OperationWrapper");
                               facade.OperationWrapper();      
            return 0;
        }
    }
}

 

名称

Flyweight

结构

意图

运用共享技术有效地支持大量细粒度的对象。

适用性

  • 一个应用程序使用了大量的对象。
  • 完全由于使用大量的对象,造成很大的存储开销。
  • 对象的大多数状态都可变为外部状态。
  • 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
  • 应用程序不依赖于对象标识。由于F l y w e i g h t 对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

Code Example

namespace Flyweight_DesignPattern
{
    using System;
          using System.Collections;
 
          class FlyweightFactory 
          {
                    private ArrayList pool = new ArrayList();
 
                    // the flyweightfactory can crete all entries in the pool at startup 
                    // (if the pool is small, and it is likely all will be used), or as 
                    // needed, if the pool si large and it is likely some will never be used
                    public FlyweightFactory()
                    {
                               pool.Add(new ConcreteEvenFlyweight());             
                               pool.Add(new ConcreteUnevenFlyweight());                     
                    }
 
                    public Flyweight GetFlyweight(int key)
                    {
                               // here we would determine if the flyweight identified by key 
                               // exists, and if so return it. If not, we would create it. 
                               // As in this demo we have implementation all the possible 
                               // flyweights we wish to use, we retrun the suitable one. 
                               int i = key % 2;
                              return((Flyweight)pool[i]); 
                    }
          }
 
          abstract class Flyweight 
          {
                    abstract public void DoOperation(int extrinsicState);                  
          }
 
          class UnsharedConcreteFlyweight : Flyweight
          {
                    override public void DoOperation(int extrinsicState)
                    {
                               
                    }
          }
 
          class ConcreteEvenFlyweight : Flyweight
          {
                    override public void DoOperation(int extrinsicState)
                    {
                               Console.WriteLine("In ConcreteEvenFlyweight.DoOperation: {0}", extrinsicState);                                                       
                    }
          }
 
          class ConcreteUnevenFlyweight : Flyweight
          {
                    override public void DoOperation(int extrinsicState)
                    {
                               Console.WriteLine("In ConcreteUnevenFlyweight.DoOperation: {0}", extrinsicState);                         
                    }         
          }
 
          /// <summary>
    ///    Summary description for Client.
    /// </summary>
    public class Client
    {
        public static int Main(string[] args)
        {
            int[] data = {1,2,3,4,5,6,7,8};
                               
                               FlyweightFactory f = new FlyweightFactory();
                               
                               int extrinsicState = 3;
                               foreach (int i in data)
                               {
                                         Flyweight flyweight = f.GetFlyweight(i);
                               flyweight.DoOperation(extrinsicState);
                               }
                               
            return 0;
        }
    }
}

 

名称

Proxy

结构

意图

为其他对象提供一种代理以控制对这个对象的访问。

适用性

  • 在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用P r o x y 模式。下面是一 些可以使用P r o x y 模式常见情况:
    1) 远程代理(Remote Proxy )为一个对象在不同的地址空间提供局部代表。 NEXTSTEP[Add94] 使用N X P r o x y 类实现了这一目的。Coplien[Cop92] 称这种代理为“大使” (A m b a s s a d o r )。
    2 )虚代理(Virtual Proxy )根据需要创建开销很大的对象。在动机一节描述的I m a g e P r o x y 就是这样一种代理的例子。
    3) 保护代理(Protection Proxy )控制对原始对象的访问。保护代理用于对象应该有不同 的访问权限的时候。例如,在C h o i c e s 操作系统[ C I R M 9 3 ]中K e m e l P r o x i e s 为操作系统对象提供 了访问保护。
    4 )智能指引(Smart Reference )取代了简单的指针,它在访问对象时执行一些附加操作。 它的典型用途包括:
  • 对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它(也称为S m a r tP o i n t e r s[ E d e 9 2 ] )。
  • 当第一次引用一个持久对象时,将它装入内存。
  • 在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

Code Example

namespace Proxy_DesignPattern
{
    using System;
          using System.Threading;
 
    /// <summary>
    ///    Summary description for Client.
    /// </summary>
    abstract class CommonSubject 
          {
                    abstract public void Request();                    
          }
 
          class ActualSubject : CommonSubject
          {
                    public ActualSubject()
                    {
                               // Assume constructor here does some operation that takes quite a
                               // while - hence the need for a proxy - to delay incurring this 
                               // delay until (and if) the actual subject is needed
                               Console.WriteLine("Starting to construct ActualSubject");              
                               Thread.Sleep(1000); // represents lots of processing! 
                               Console.WriteLine("Finished constructing ActualSubject");
                    }
                               
                               override public void Request()
                    {
                               Console.WriteLine("Executing request in ActualSubject");
                    }
          }
 
          class Proxy : CommonSubject
          {
                    ActualSubject actualSubject;
 
                    override public void Request()
                    {
                               if (actualSubject == null)
                                         actualSubject = new ActualSubject();
                               actualSubject.Request();
                    }         
                    
          }
          
          public class Client
    {
        public static int Main(string[] args)
        {
                               Proxy p = new Proxy();
 
                               // Perform actions here
                               // . . . 
 
                               if (1==1)           // at some later point, based on a condition, 
                                         p.Request();// we determine if we need to use subject
                                                               
            return 0;
        }
    }
}