适配器模式

内容摘录自《大话设计模式》

 

适配器模式

适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

简单地说,就是需要的东西就在面前,但却不能使用,而短时间内又无法改造它,于是我们就想办法适配它。

示例1:电源适配器。有些国家用110V电压,而我们国家用的是220V,但我们的电器,比如笔记本电脑是不能什么电压都能用的,但国家不同,电压可能不相同也是事实,于是就用一个电源适配器,只要是电,不管多少伏,都能把电源变成需要的电压,这就是电源适配器的作用。适配器的意思就是使得一个东西适合另一个东西。

示例2:姚明的翻译。姚明刚到NBA打球,不会英语如何交流?此时翻译就相当于适配器。

在我们不能更改球队的教练、球员和姚明的前提下,我们能做的就是想办法找个适配器。在软件开发中,也就是系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个对象与接口匹配。适配器模式主要用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。

适配器模式_第1张图片

Target(这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口)

class Target{
	public virtual void Request()
    {
        Debug.Log("普通请求!");
    }
}

Adaptee(需要适配的类)

class Adaptee
{
    public void SpecificRequest()
    {
        Debug.Log("特殊请求!");
    }
}

Adapter(通过在内部包装一个adaptee对象,把原接口转换成目标接口)

class Adapter : Target
{
    private Adaptee adaptee = new Adaptee();    // 建立一个私有的Adaptee对象
    public override void Request()
    {
        adaptee.SpecificRequest();  // 这样就可以把表面上调用Request()方法变成实际调用SpecificRequest()
    }
}

客户端代码

        Target target = new Adapter();
        target.Request();

 

何时使用适配器模式

想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就可以考虑用适配器模式。也就是说,两个类所做的事情相同或相似,但是具有不同的接口时要使用它。由于类都共享同一个接口,客户代码可以统一调用同一接口就行了,这样可以更简单、更直接、更紧凑。

通常都是在软件开发后期或维护期再考虑使用它。如果是在世界阶段,类似的功能类的接口应该是相同的。在双方都不太容易修改的时候再使用适配器模式适配

当然,也有在设计之初就需要考虑用适配器模式的时候。比如公司设计一系统时考虑使用第三方开发组件,而这个组件的接口与我们自己的系统接口是不相同的,而我们也完全没有必要为了迎合它而改动自己的接口,此时就可以考虑用适配器模式来解决接口不同的问题。

 

篮球翻译适配器

后卫、中锋、前锋都是球员,所以应该有一个球员抽象类,有进步和防守的方法。

球员类

// 球员
abstract class Player
{
    protected string name;
    public Player(string _name)
    {
        name = _name;
    }

    public abstract void Attack();
    public abstract void Defense();
}

后卫、中锋、前锋类

// 前锋
class Forwards : Player
{
    public Forwards(string name):base(name)
    {
    }
    public override void Attack()
    {
        Debug.Log(string.Format("前锋 {0} 进攻", name));
    }
    public override void Defense()
    {
        Debug.Log(string.Format("前锋 {0} 防守", name));
    }
}
//中锋
class Center : Player
{
    // 与前锋代码类似,略
}
//后卫
class Guards : Player
{
    // 与前锋代码类似,略
}

外籍中锋

//外籍中锋
class ForeignCenter
{
    private string name;
    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public void 进攻()
    {
        Debug.Log(string.Format("外籍中锋 {0} 进攻", name));
    }

    public void 防守()
    {
        Debug.Log(string.Format("外籍中锋 {0} 防守", name));
    }
}

翻译者类

// 翻译者
class Translator : Player
{
    private ForeignCenter foreignCenter = new ForeignCenter();

    public Translator(string name) : base(name)
    {
        foreignCenter.Name = name;
    }

    public override void Attack()
    {
        foreignCenter.进攻();
    }

    public override void Defense()
    {
        foreignCenter.防守();
    }
}

客户端代码

        Player b = new Forwards("巴蒂尔");
        b.Attack();

        Player ym = new Translator("姚明");
        ym.Attack();
        ym.Defense();

适配器模式_第2张图片

尽管姚明曾经是不太懂英文,尽管火箭教练和球员也不会学中文,但因为有了翻译者,团队沟通合作成为了可能。

 

你可能感兴趣的:(设计模式)