(2010-08-19)C#设计模式之适配器模式

    我想学习C#或者JAVA等面向对象语言的人来说,要在脑中形成面向对象的思想,就必须多次学习,也就是反复学习设计模式。当然我这里说的反复学习并不是指的是把设计模式教程一遍一遍的看,我指的是每间隔一段时间再重新阅读思考设计模式。也就是经过项目的实践,然后再回过头思考设计模式在项目中的运用。再者就是需要把设计模式的思想融入到现实生活中来,我想只有这样才能在脑中无形形成面向对象的思考思维,也只有这样才能让自己的项目一次比一次敏捷。

    再说点题外话,工作一年多,感觉无论哪一方面只要专心钻研,坚持不懈,必能达到一定的高度,成为一名合格的IT工作者。

    记得刚接触设计模式也是很偶然的,在网上随便乱逛时发现了一本评价非常高的关于设计模式的书《大话设计模式》,我想应该很多人都知道这本书吧,确实很不错。我的面向对象思想可以说就是从《大话设计模式》开始的,如今已经工作一年多,设计模式也偶尔翻翻,效果不甚理想,因为自己时间分配得不够好。今后要调整调整了。

    今天呢重新拿起设计模式的书来学习下,忽然感觉自己思路宽了很多,我想这是进步吧。无形中的进步,让我着实高兴,也坚定了我的思想,乘着现在这份心情,把今天设计模式学习心得体会记录下来吧。

   今天上午学的是适配器模式,并在学习该模式的过程中联系了一个现实生活中的例子。

   我想今天规范下自己写博文的格式吧,就按问题的提出、设计模式的说明、现实中的例子说明、总结的格式吧。

(1)问题的提出:

     在实际开发过程中,我们经常遇到这样的事情,我们根据初步的需求制定了一个基类,在开发过程中才了解到详细的需求或者需求发生了变动。而开发工作中的接口早已经定义完毕,并已经大规模投入编码。此时若改动接口的定义会造成很多编码上重复性的修改工作,并进而有可能造成修改不完全而导致的语义错误或逻辑错误。语义错误尚可以在编译阶段发现,而一旦发生逻辑性的错误,后果将会非常严重,甚至足以导致系统崩溃。在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。那么如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?此时就需要用到适配器模式的设计方法。

 

(2)适配器模式说明:

适配器模式主要应用于,当接口里定义的方法无法满足客户的需求,或者说接口里定义的方法的名称或者方法界面与客户需求有冲突的情况。

适配器模式的使用方法:
用一个类同时继承接口和已知类,利用已知类中定义的方法和属性等,实现接口中的定义(主要利用了重载接口方法的办法)。用此类作为其他业务类的基类,也就是这个类适配了接口和已知类。若已知类发生变化,只需修改类适配器,就可以满足接口的实现。

具体示例如下(代码均采用书中的代码,某些代码可能进行了简化)。
有定义好的接口如下:

interface  IRocketSim
{
  float
 GetMass();
  float
 GetThrust();
  void SetSimTime(float
 f);
}

实际需要的已知类如此定义:

public class  PhysicalRocket
{
  PhysicalRocket(
float burnArea, float burnRate, float fuelMass, float
 totalMass);
  
public float
 GetBurnTime()
  
{
  }

  
public float GetMass(float f)
  
{
  }

  
public float GetThrust(float f)
  
{
  }

}

此时,实际需要的已知类和已经定义的接口是有差别的,此时我们就需要一个适配器类来适配已知类和接口。

public class  OozinozRocket
{
  
private float
 _time;
  
public OozinozRocket(float burnArea, float burnRate, float fuelMass, float totlMass) : base
(burnArea, burnRate, fuelMass, totlMass)
  
{
  }

  
public float GetMass()
  
{
    return
base
.GetMass(this._time);
  }

  
public float GetThrust()
  
{
    return
base
.GetThrust(this._time);
  }

  
public void SetSimTime(f time)
  
{
    this._time 
=
 time;
  }

}

 

接口也就是定义了一套固定的行为。适配器模式就是实现了此类接口,并能够提供客户所需服务的类的子类。此类适配器模式称为类适配器。

当没有定义客户接口的时候,我们也可以使用适配器模式,这类适配器叫“对象适配器”。与类适配器不同的是,它不是继承已知类,而是将已知类作为类的成员变量,实例化一个已知类的对象,利用此对象的方法来实现适配。
上面的例子将用下面的方式实现。Skyrocket类是OozinozSkyrocket要遵守的行为类,不是定义的接口。

public class  Skyrocket
{
  protect 
float
 _simTime;
  
public Skyrocket(float mass, float thrust, float
 burnTime)
  
{
  }

  
float GetMass()
  
{
  }

  
float GetThrust()
  
{
  }

  
void SetSimTime(float f)
  
{
  }

}

此时,需要的对象适配器如下:

public class  OozinozSkyrocket:Skyrocket
{
  
private
 PhysicalRocket _rocket;
  
public OozinozSkyrocket(PhysicalRocket r) : base(r.GetMass(0), r.GetThrust(0
), r.GetBurnTime())
  
{
    
this._rocket =
 r;
  }

  
public float GetMass()
  
{
    
return this._rocket.GetMass(base
._simTime);
  }

  
public float GetThrust()
  
{
    
return this._rocket.GetThrust(base
._simTime);
  }

}

类适配器相对于对象适配器的优势在于:
类适配器是定义了接口规范的,而对象适配器的规范类一旦发生变化(定义方法内部的改变),可能导致运行时出错。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值