设计模式记录3之“装饰者模式”

概念:

在软件中,对于功能的扩展,我们会有时候会使用继承来实现对象扩展功能。但是由于继承为类型引入的静态特质,所以缺乏灵活性并且随着功能的增多子类会膨胀。

我们如何避免这种情况呢?可以用到装饰者模式。

定义:动态的给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

装饰者模式采用组合,非继承的方式,解决主体类在多个方向上的扩展功能。实现了在运行时动态的扩展对象的功能,根据需要扩展多个功能,避免了单独使用继承带来的"灵活性差"和"多子类衍生的问题",但是它并非是解决多子类衍生的继承问题。

场景:

比如手机可以有很多功能,有通话功能,拍照功能,短信功能,视频通话功能.... 而手机是分为很多中的,有的没有视频通话功能,只需要通话和短信功能,有的需要通话,短信功能和拍照功能。每种的手机功能是不同。在程序角度看,在此时我们就可以考虑使用"装饰者模式"。流程图是这样的:

 

现在开始实现步骤。

step 1:

建立一个手机抽象类类,其中定义了手机的品牌和型号,以及它所具有的功能抽象方法: 

 /// <summary>
    
/// 手机抽象类
    
/// </summary>
    public abstract  class Phone
    {
        
private string name; //手机的品牌
        public string Name
        {
            
get { return name; }
            
set { name = value; }
        }
        
private string vevison;//手机型号
        public string Vevison
        {
            
get { return vevison; }
            
set { vevison = value; }
        }
        
public abstract void Function(); //手机功能抽象方法
   
    }

 step 2,创建一个Decorator功能抽象类,继承Phone。作用:用于创建手机功能

/// <summary>
    
/// 功能抽象类,继承Phone类
    
/// 只是一个接口继承不是类继承。
    
/// 注:接口继承只是继承了一合同,类继承是继承具体实现
    
/// </summary>
    public abstract class Decorate:Phone
    {
        
protected Phone phone;    
        
public Decorate(Phone _pone) 
        {
            
this.phone=_pone; //构造器
        }

        
public override void Function()
        {
           
if(phone!=null)
           {
               phone.Function();
           }
        }

    }

 step 3,创建具体对象类PhoneSon,继承自Phone。作用:用于创建多个手机对象。

 /// <summary>
    
/// 具体手机对象,继承自Phone
    
/// </summary>
    class PhoneSon:Phone
    {
        
public PhoneSon(string name,string vevison)
        {
            
this.Name = name;
            
this.Vevison = vevison;
        }
        
public override void Function()
        {
            Console.WriteLine(
"这是一个品牌为{0}的手机,手机版本是{1}",this.Name,this.Vevison);
        }
    }

 step 3,创建各个功能,比如拍照功能,通话功能... 继承自Decorate抽象类:

/// <summary>
    
/// 功能扩展A
    
/// </summary>
    public class DecoratorA:Decorate
    {
        
public DecoratorA(Phone p)
            : 
base(p)
        {
        }
        
public override void Function()
        {
            
base.Function();
            Console.WriteLine(
"A照相功能扩展");
        }
    }
 
   /// <summary>
    
/// B功能扩展
    
/// </summary>
    public class DecoratorB:Decorate
    {
        
public DecoratorB(Phone p)
            : 
base(p)
        { }
        
public override void Function()
        {
            
base.Function();
            Console.WriteLine(
"B聊天功能扩展");
        }

    }
       /// <summary>
      
/// B功能扩展
      
/// </summary>
      
public DecorateC(Phone p)
            : 
base(p)
        { }
        
public override void Function()
        {
            
base.Function();
            Console.WriteLine(
"C扩展了短信功能");
        }

 step 4,客户端动态的添加手机所需要的功能:

/// <summary>
        
/// 客户端
        
/// </summary>
        
/// <param name="args"></param>
        static void Main(string[] args)
        {
            
//第一个手机  
            Phone p1 = new PhoneSon("诺基亚""5230");  //实例化1个手机
            DecoratorA A = new DecoratorA(p1);    //装饰它的功能
            A.Function();
            Console.WriteLine();

            
//第二个手机
            Phone p2=new PhoneSon("HTC","G7");  //实例化
            DecoratorA A1 = new DecoratorA(p2); //装饰它的功能
            DecoratorB b1 = new DecoratorB(A1);
            DecorateC C1 
= new DecorateC(b1);
            C1.Function();

            Console.ReadLine();

 输出结果为:

 

 从上面的输出结果,可以知道,PhoneSon抽象类创建具体的手机对象,而Decorator抽象类创建了手机的各个功能的对象。最后在客户端动态的根据需求组合出一部手机。

当我们需要增加功能,比如上网功能,那么我们就可以增加一个这个样的类:

 public class DecoratorD:Decorate
    {
        
public DecoratorD(Phone p)
            : 
base(p)
        { }

        
public override void Function()
        {
            
base.Function();
            Console.WriteLine(
"C扩展了上网功能");
        }
    }

 在客户端我们可以这样做:

/// <summary>
        
/// 客户端
        
/// </summary>
        
/// <param name="args"></param>
        static void Main(string[] args)
        {
            
//具有上网功能的手机
            Phone p3 = new PhoneSon("三星","S6480");//实例化第三个手机
            DecoratorB b2 = new DecoratorB(p3);
            DecoratorD d3 
= new DecoratorD(b2);
            d3.Function();
            Console.ReadLine();

        }

 输出结果:

 

 

装饰者模式缺点:

 由于使用装饰者模式,会产生比使用继承关系更多的对象。

posted @ 2011-04-23 14:27  淹死的鱼  阅读(340)  评论(0编辑  收藏  举报