前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >五分钟就能学会的适配器模式,告别多个上游的烦恼

五分钟就能学会的适配器模式,告别多个上游的烦恼

作者头像
TechFlow-承志
发布2021-01-07 10:37:13
4260
发布2021-01-07 10:37:13
举报
文章被收录于专栏:TechFlow

大家好,今天给大家介绍Adapter模式,即适配器模式。

说到适配器大家可能想到的都是充电器以及各种电器的电源,其实适配器还有一层含义是电源的转接器。比如下图的东西在英文当中也叫做Adapter。我们这里说的适配器的含义就是指的这个。

为什么需要适配器?

我们为什么需要适配器呢?其实和现实中的原因是一样的,因为接口不匹配。大家有经历过跨国旅行的话,应该都知道现在国际上的插座分为好几个标准,有英式插座,也有美式插座,还有欧式插座。不同种类的插座之间不能互相通用,这样就很难受,如果没有适配器做中转的话,我们的电器都没有办法正常使用。

同理,在代码当中也是一样的,比如首页展示的商品有好几个源头,有些来源于广告系统,有些来源于推荐系统,还有些是运营手动配的,来源于投放系统。但是由于历史原因,这些接口的格式也都不相同,那么对于使用者来说就非常蛋疼,我们需要手动去适配这些接口, 这样导致的结果就是写出来的代码比较丑而且还冗长,不利于维护。

所以这里有一个解决方案就是通过适配器来适配不同的接口,这样我们就可以通过同一个接口来调用所有不同的方法。

代码实现

Adapter的代码实现也非常简单,也属于看完代码就会使用的典型。

代码语言:javascript
复制
class Adapter:

    def __init__(self, obj, **adapted_methods):
        self.obj = obj
        self.__dict__.update(adapted_methods)

    def __getattr__(self, attr):
        return getattr(self.obj, attr)

    def original_dict(self):
        return self.obj.__dict__

如果我们忽略最后一个origin_dict方法的话,它只有两个方法,一共3行代码。我们着重看下init方法,当中其实只有一个逻辑,就是从外界传入一个叫做adapted_methods的dict,然后会将这个dict更新到Adapter本身。我们都知道在Python当中传参的时候,如果我们以默认参数的形式传参,实际上都会被转化成dict的形式。所以看起来传入的是一个dict,实际上只是一些默认形式传入的参数而已。

也就是说我们在初始化Adaptor的时候,只需要通过默认参数的方法传入我们需要适配的方法名即可。这里举个例子:

代码语言:javascript
复制
adapter = Adapter(obj, getElement=lambda x: x['abc'] + 3)

由于我们在__getattr__方法当中做了映射,这样我们直接调用adapter.getElement()就可以生效。

最后我们来看一个完整的例子:

代码语言:javascript
复制
class Dog:
    def __init__(self):
        self.name = 'Dog'

    def bark(self):
        return 'woof'

class Cat:
    def __init__(self):
        self.name = 'Cat'

    def meow(self):
        return 'meow'

class Human:
    def __init__(self):
        self.name = 'Human'

    def speak(self):
        return "'hello'"


class Car:
    def __init__(self):
        self.name = 'Car'

    def make_noise(self, octane_level):
        return 'vroom{0}'.format("!" * octane_level)


class Adapter:

    def __init__(self, obj, **adapted_methods):
        self.obj = obj
        self.__dict__.update(adapted_methods)

    def __getattr__(self, attr):
        return getattr(self.obj, attr)

    def original_dict(self):
        return self.obj.__dict__


if __name__ == '__main__':
    objects = []
    dog = Dog()
    cat = Cat()
    human = Human()
    car = Car()
    objects.append(Adapter(dog, make_noise=dog.bark))
    objects.append(Adapter(cat, make_noise=cat.meow))
    objects.append(Adapter(human, make_noise=human.speak))
    objects.append(Adapter(car, make_noise=lambda: car.make_noise(3)))

    for obj in objects:
        print('A {0} goes {1}'.format(obj.name, obj.make_noise()))

在这个例子当中,我们实现了几种会发出声音的类,比如狗、猫、人、汽车等等。但是不同的事物发出声音的方式是不同的,比如人类就是说话,汽车则是鸣笛,猫和狗也都有各自的叫声。我们单独使用这些类当然是没有问题,但如果我们希望通过一种方式能够统一调用就做不到了。所以这里才引入了Adapter类,作为中转,这样就可以通过一个数组来遍历调用所有的实例,即使它们的方法名和参数都不相同。

Adapter模式也是一种自底向上进行抽象的模式,和之前介绍的委托模式有一点类似,两者的底层原理是一样的,只是实现的方法略有不同。其实落实到我们最终项目当中的设计模式是怎样的并不太重要,因为设计模式天然就是拿来用的,相比于是否严格遵守了某一种模式,更加贴近使用者的诉求更加重要。所以大家不必太过在意形式,哪怕最终写出来有一点四不像也没有关系,只要能够实际解决问题,为开发带来便利就好。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Coder梁 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么需要适配器?
  • 代码实现
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档