装饰模式(Decorator/Wrapper Pattern)

来源:互联网 发布:压力传感器数据采集 编辑:程序博客网 时间:2024/05/16 07:38
  • 抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
  • 具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
  • 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
  • 具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加的责任。 
  •  

    // Decorator pattern -- Structural example  
    using System;

    // "Component"
    abstract class Component
    {
      
    // Methods
      abstract public void Operation();
    }


    // "ConcreteComponent"
    class ConcreteComponent : Component
    {
      
    // Methods
      override public void Operation()
      
    {
        Console.WriteLine(
    "ConcreteComponent.Operation()");
      }

    }


    // "Decorator"
    abstract class Decorator : Component
    {
      
    // Fields
      protected Component component;

      
    // Methods
      public void SetComponent( Component component )
      
    {
        
    this.component = component;
      }


      
    override public void Operation()
      
    {
        
    if( component != null )
          component.Operation();
      }

    }


    // "ConcreteDecoratorA"
    class ConcreteDecoratorA : Decorator
    {
      
    // Fields
      private string addedState;

      
    // Methods
      override public void Operation()
      
    {
        
    base.Operation();
        addedState 
    = "new state";
        Console.WriteLine(
    "ConcreteDecoratorA.Operation()");
      }

    }


    // "ConcreteDecoratorB"
    class ConcreteDecoratorB : Decorator
    {
      
    // Methods
      override public void Operation()
      
    {
        
    base.Operation();
        AddedBehavior();
        Console.WriteLine(
    "ConcreteDecoratorB.Operation()");
      }


      
    void AddedBehavior()
      
    {
      }

    }


    /**//// <summary>
    /// Client test
    /// </summary>

    public class Client
    {
      
    public static void Main( string[] args )
      
    {
        
    // Create ConcreteComponent and two Decorators
        ConcreteComponent c = new ConcreteComponent();
        ConcreteDecoratorA d1 
    = new ConcreteDecoratorA();
        ConcreteDecoratorB d2 
    = new ConcreteDecoratorB();

        
    // Link decorators
        d1.SetComponent( c );
        d2.SetComponent( d1 );

        d2.Operation();
      }

    }

     

    在以下情况下应当使用装饰模式:

    1. 需要扩展一个类的功能,或给一个类增加附加责任。
    2. 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
    3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。

    装饰模式实际应用的例子,该例子演示了通过装饰模式为图书馆的图书与录像带添加"可借阅"装饰。

     

    // Decorator pattern -- Real World example  
    using System;
    using System.Collections;

    // "Component"
    abstract class LibraryItem
    {
      
    // Fields
      private int numCopies;

      
    // Properties
      public int NumCopies
      
    {
        
    getreturn numCopies; }
        
    set{ numCopies = value; }
      }


      
    // Methods
      public abstract void Display();
    }


    // "ConcreteComponent"
    class Book : LibraryItem
    {
      
    // Fields
      private string author;
      
    private string title;

      
    // Constructors
      public Book(string author,string title,int numCopies)
      
    {
        
    this.author = author;
        
    this.title = title;
        
    this.NumCopies = numCopies;
      }


      
    // Methods
      public override void Display()
      
    {
        Console.WriteLine( 
    " Book ------ " );
        Console.WriteLine( 
    " Author: {0}", author );
        Console.WriteLine( 
    " Title: {0}", title );
        Console.WriteLine( 
    " # Copies: {0}", NumCopies );
      }

    }


    // "ConcreteComponent"
    class Video : LibraryItem
    {
      
    // Fields
      private string director;
      
    private string title;
      
    private int playTime;

      
    // Constructor
      public Video( string director, string title,
        
    int numCopies, int playTime )
      
    {
        
    this.director = director;
        
    this.title = title;
        
    this.NumCopies = numCopies;
        
    this.playTime = playTime;
      }


      
    // Methods
      public override void Display()
      
    {
        Console.WriteLine( 
    " Video ----- " );
        Console.WriteLine( 
    " Director: {0}", director );
        Console.WriteLine( 
    " Title: {0}", title );
        Console.WriteLine( 
    " # Copies: {0}", NumCopies );
        Console.WriteLine( 
    " Playtime: {0}", playTime );
      }

    }


    // "Decorator"
    abstract class Decorator : LibraryItem
    {
      
    // Fields
      protected LibraryItem libraryItem;

      
    // Constructors
      public Decorator ( LibraryItem libraryItem )
      
    this.libraryItem = libraryItem; }

      
    // Methods
      public override void Display()
      
    { libraryItem.Display(); }
    }


    // "ConcreteDecorator"
    class Borrowable : Decorator
    {
      
    // Fields
      protected ArrayList borrowers = new ArrayList();

      
    // Constructors
      public Borrowable( LibraryItem libraryItem )
        : 
    base( libraryItem ) {}

      
    // Methods
      public void BorrowItem( string name )
      
    {
        borrowers.Add( name );
        libraryItem.NumCopies
    --;
      }


      
    public void ReturnItem( string name )
      
    {
        borrowers.Remove( name );
        libraryItem.NumCopies
    ++;
      }


      
    public override void Display()
      
    {
        
    base.Display();
        
    foreachstring borrower in borrowers )
          Console.WriteLine( 
    " borrower: {0}", borrower );
      }

    }

     
    /**//// <summary>
    ///  DecoratorApp test
    /// </summary>

    public class DecoratorApp
    {
      
    public static void Main( string[] args )
      
    {
        
    // Create book and video and display
        Book book = new Book( "Schnell""My Home"10 );
        Video video 
    = new Video( "Spielberg",
          
    "Schindler's list"2360 );
        book.Display();
        video.Display();

        
    // Make video borrowable, then borrow and display
        Console.WriteLine( " Video made borrowable:" );
        Borrowable borrowvideo 
    = new Borrowable( video );
        borrowvideo.BorrowItem( 
    "Cindy Lopez" );
        borrowvideo.BorrowItem( 
    "Samuel King" );

        borrowvideo.Display();
      }

    }

     

    使用装饰模式主要有以下的优点:

    1. 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
    2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
    3. 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错。

    使用装饰模式主要有以下的缺点:

    由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。

    原创粉丝点击