设计模式历险记之适配器模式

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

我们先来看看它的结构图:

从上面结构图可知,一个客户端类需要请求目标类或者是目标抽象,存在一个适配器继承了目标了或者是实现了目标抽象,并且将客户端的请求转移到了被适配的对象。

举一个栗子吧:

现在有这样一种场景:你正在开发电商平台的收费系统,因为平台上不定期会搞一些活动,所以可能存在有不同的收费方式,假设有三种收费方式分别为 A 、B 和 C ,下面我们来用代码表示出来:

<?php
class CashierDesk{
    private $cashierMethod;

    //注入收费方式
    public function __construct(cashierMethod $cashierMethod){
        $this->cashierMethod = $cashierMethod;
    }

    //获取收费金额
    public function getMoney(){
        $this->cashierMethod->getMoney();
    }
}

interface cashierMethod{
    public function getMoney(){

    }
}

class A implements cashierMethod{
    public function getMoney(){
        //收费方式A的逻辑
    }
}

class B implements cashierMethod{
    public function getMoney(){
        //收费方式B的逻辑
    }
}

当你写到收费方式B的时候,这个时候你的同事突然告诉你,
它以前有写过一种收费方式 D,并且和收费方式 C 功能一样,只是调用的方式不一样,我们看一下同事以前写的收费 D:

<?php
//同事写的收费方式D
class D{
    public function getMoneyForD(){
        //收费方式D的逻辑
    }
}

这个是你第一想法,可能是将这个方法 D 重构一下,
你把这个想法告诉了你的同事,你同事说不行的,这个收费类 D 你不能改,因为我项目中还有其它的地方使用了它。
这个时候适配器模式就可以大显身手了,看下面代码:

//写一个D收费方法的适配器,通过这个适配器将收费请求转移到收费方法D中
//这个时候我们任可以在收银台注入这个适配器来使用收费方法 D。
class CToAdaterByD implements cashierMethod{

    //被装饰的对象
    private $adatee = new D();

    //收银台调用的获取金额方法
    public function getMoney(){
        $this->adatee->getMoney();
    }

}

通过适配器模式适配了收费方法 D ,这样能明显的感觉到这样写的好处。

  • 代码复用了,有了和收费方式 C 类似的收费方式 D ,虽热两个方法调用的方式可能不一样,但是通过适配器适配后,就能将它复用,无需在此写相同逻辑代码。

我们来总结一下上面的逻辑:

电商平台有不同的收费方式,
电商平台收费有一个统一的位置就是收银台,
通过收银台的公共方法 getMoney() 来获取收费金额,
当我们写了收银方法 A 和 B 后,发现系统中有一个已存在的收银方法 D ,
这个收银方法 D 和收银方法 C 功能一样但是调用的方式不一样,
你不能去重构收银方法 D ,因为你不知道系统中哪里还有调用 D,
这时可以通过适配器来将收银方法 D 适配调用它的收银台,
这样在不影响系统中其它调用收银方法 D 的情况下复用了它。

总结一下吧:

适配器模式是当你想用已存在的类或者方法的时候,但是又不满足直接使用的条件的时候,这时可以用适配器模式来适配该类或方法从而达到能使用它的目的。

这里需要注意,上面关于电商品台收银的例子如果你不用适配器模式,那么你任然可以重写一个收费方式 C ,只是这样代码会很冗余,不推荐,但确实又能这样写。
某些情况如果你需要接入某三方的接口到你的系统,发现你系统的接入口不满足第三方接口的接入条件,再假如你的接入口不能再修改,然后三方接口你也不能修改,那么这个时候解决的办法就只有用适配器模式了。

Snail's Blog
请先登录后发表评论
  • 最新评论
  • 总共1条评论
Snail's Blog

Reflection.Snail's Blog

2018-08-16 11:14:22 回复

Snail's Blog
  • snail-C 回复 Reflection.Snail's Blog
  • 2018-08-16 11:15:13 回复
Snail's Blog
  • snail-C 回复 snail-CSnail's Blog
  • 2018-08-16 11:17:32 回复
  • 本博客使用免费开源的 laravel-bjyblog v5.5.1.3 -develop 搭建 © 2014-2018 www.snail-c.cn 版权所有 ICP证:蜀ICP备18023253号-1
  • 联系邮箱:459921737@qq.com