小话设计模式(六)适配器模式
2016-09-26 08:56
162 查看
适配器(Adapter)又名包装器(Wrapper),将一个类的接口转换成用户希望的另外一个接口,使得原本接口不兼容的类可以一起工作。
适配器又分为类适配器和对象适配器,而类适配器的实现需要多重继承,而C#并不支持多重继承,所以本文只讨论对象适配器。
假设我们的游戏中有两种类:植物和动物,植物可以被采集,动物有血量可以被攻击(这里简化为被动物攻击,人也是动物的一种嘛),血量低于零死亡。
定义如下:
这时候策划过来了,对你说,我们需要一种食人花,有血量可以被攻击,也可以攻击别人,但是死亡后掉落种子。
这就很尴尬了,因为一开始并没有考虑到这种情况,为Plant添加hp、atk属性和BeAttacked方法可能并不合适,因为这意味着你要把Animal类里的代码写两遍,这显然不利于维护。而Plant可能本身就继承自其他类,这种情况下也无法让它继承Animal。而且这也违反了接口隔离原则,以及组合/聚合复用原则。
这时候,你可以考虑适配器模式:
使用:
这样就似乎很好的解决了食人花的问题。
但是不得不说的是,适配器模式是一种没有办法的办法。如果可能的话,尽量在程序设计之初就考虑到这样的问题,编写出一种更合理的继承关系(例如Plant和Animal都继承自Creature类,Creature里包含血量和攻击力等属性,而Plant里面这两个值都为0)。或者在程序完成度还不高的时候,及时重构。只有在不得已的情况下(例如程序编写已经进入后期,重构代价会很大)才会考虑适配器模式。
适配器模式另外一种用途,就是统一外部API的接口。例如小话设计模式(三)抽象工厂模式中提到的Android和IOS的适配问题,对于AndroidKeyboard和IOSKeyboard这样具体实现接口转换的类,它们本身就是适配器模式的实际应用。
适配器又分为类适配器和对象适配器,而类适配器的实现需要多重继承,而C#并不支持多重继承,所以本文只讨论对象适配器。
假设我们的游戏中有两种类:植物和动物,植物可以被采集,动物有血量可以被攻击(这里简化为被动物攻击,人也是动物的一种嘛),血量低于零死亡。
定义如下:
public class Plant { public virtual void BeCollected() { Console.WriteLine ("Drop seeds"); } } public class Animal { public int hp { get; private set;} public int atk {get; private set;} public Animal() { hp = 100; atk = 20; } public void BeAttacked(Animal attacker) { if (hp > 0) { hp -= attacker.atk; } if (hp <= 0) { AnimalDead (); } } protected virtual void AnimalDead() { Console.WriteLine ("Drop meat"); } }使用:
Plant plant = new Plant (); plant.BeCollected (); Animal animal = new Animal (); Animal attacker = new Animal (); while (animal.hp > 0) { animal.BeAttacked (attacker); }
这时候策划过来了,对你说,我们需要一种食人花,有血量可以被攻击,也可以攻击别人,但是死亡后掉落种子。
这就很尴尬了,因为一开始并没有考虑到这种情况,为Plant添加hp、atk属性和BeAttacked方法可能并不合适,因为这意味着你要把Animal类里的代码写两遍,这显然不利于维护。而Plant可能本身就继承自其他类,这种情况下也无法让它继承Animal。而且这也违反了接口隔离原则,以及组合/聚合复用原则。
这时候,你可以考虑适配器模式:
public class PiranhaAdapter : Animal { private Plant _plant = new Plant(); protected override void AnimalDead() { _plant.BeCollected (); } }
使用:
PiranhaAdapter piranha = new PiranhaAdapter (); while (piranha.hp > 0) { piranha.BeAttacked (attacker); }
这样就似乎很好的解决了食人花的问题。
但是不得不说的是,适配器模式是一种没有办法的办法。如果可能的话,尽量在程序设计之初就考虑到这样的问题,编写出一种更合理的继承关系(例如Plant和Animal都继承自Creature类,Creature里包含血量和攻击力等属性,而Plant里面这两个值都为0)。或者在程序完成度还不高的时候,及时重构。只有在不得已的情况下(例如程序编写已经进入后期,重构代价会很大)才会考虑适配器模式。
适配器模式另外一种用途,就是统一外部API的接口。例如小话设计模式(三)抽象工厂模式中提到的Android和IOS的适配问题,对于AndroidKeyboard和IOSKeyboard这样具体实现接口转换的类,它们本身就是适配器模式的实际应用。
相关文章推荐
- 结构型设计模式---Adapter模式(适配器模式)
- 设计模式[3] Adapter 适配器模式
- 设计模式c#语言描述&#8212;&#8212;适配器模式
- Head First 设计模式之适配器模式学习
- Java设计模式之适配器模式
- 深入浅出Java设计模式之适配器模式
- 设计模式学习(七)适配器模式
- 设计模式1-适配器模式(Adapter)
- 设计模式 - Adapter Pattern(适配器模式)
- 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern)
- 结合实现谈设计模式——适配器模式
- 深入浅出Java设计模式之适配器模式
- 设计模式——适配器模式
- .NET设计模式-适配器模式(Adapter Pattern)
- Dot Net设计模式—适配器模式
- 设计模式c#语言描述——建造者模式、适配器模式、合成(Composite)模式
- 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern)
- Java设计模式之适配器模式
- .NET设计模式(8):适配器模式(Adapter Pattern)
- 设计模式(9)-适配器模式(Adapter)