设计心得—隔离变化的实现方法之适配器

一、隔离变化和适配器

在前面的文章中分析了很多解耦和隔离变化的方法,它们更多的是从理论的角度来进行分析和说明。本文通过适配器的设计模式来进行一种实践角度的说明和分析。从实践到理论是一个很考验人的抽象能力的问题。但是,反过来,从理论到实践对人的要求也很高,但它更高的往往是人的理解和行动力。
适配器做为一种在设计和代码开发中都经常遇到的一种技术实践方式,更容易为开发者所理解和应用。所谓适配器,很好理解,就是把不同的模块通过它能连接起来。举个例子,家里有一个水管很粗,而买了个水龙头有点细,那么可以去五金店买一个一头大一头小的连接管装上就行了。这个连接管就是一个适配器。

二、应用场景

最典型的适配器就是数据库的应用。不同的数据库的接口,可以通过适配器适配到同个数据访问接口。就比如公司一开始可能只有一种数据库接口如使用sqlserver,但后来又增加了oracle,不断的扩展。那么设计者就可以抽象出一个适配器层来满足新数据库的接口扩展能力。
同样,类似的如不同的日志框架、类似的第三方库等。说白了,凡是想把不同的接口应用搞到同一个接口上的,都可以使用适配器的设计模式。适配器更倾向于一种“胶水”,而“胶水”往往意味着不建议随意的应用。

三、适配器工程实践

假如世界都是标准的,假如世界这个标准是不变化的,更假如人们都如德国人的想法一样刻板的。那么极有可能就没有适配器这一说。但可惜的是,这个世界是自由的,万物都按照自己的意愿在不同的发展着。同样,计算机世界也是如此。软件的设计者既想快速安全的实现某个功能,又不想把时间放到一些对自己没有什么意义的模块上。那么,可能就需要使用第三方的或别人的模块,而别人的模块是为别人设计服务的,虽然能满足设计者的功能,但有些细节很可能与设计者的想法有所不同。
正如前面提到的水龙头的安装,当然还更多类似的例子,比如显示器的接口与显卡的接口不同,就有一种转换器,把HDMI转成DP或者其它的都可以。这个转换器就是一个适配器。适配器的核心就如软件设计的方法一样,把问题抽象一层,看能不能解决二者的问题。如果不能,就再抽象一层。也就是说,适配器就是软件抽象的结果。适配器的优势在于,它可以弥补大家的“异”而求大家的“同”。这也是刚刚将其描述为“胶水”的原因。
适配器是一种灵活应用的手段或者说设计模式,如果灵活的代价与实际的所得不成比例,那么就要考虑是否需要这种灵活性。设计者在任何时候都需要考虑实际应用的需求以及为达到这种需求的实现而进行各方面的协调和平衡。
当然,在实际的实践过程中,还是有一些原则需要遵守的:

  1. 单一职责原则
    这个很好理解,既然适配,就不要啥种类都想适配,搞得不知道是个什么样的适配器,用起来也不方便
  2. 简单原则
    尽量保持接口的统一、功能的简单,即在单一的基础还要尽量保持功能最小化
  3. 引入依赖注入等设计处理
    适配器,要尽量保证接口的隔离性,而隔离性的方式就包括依赖注入等
  4. 考虑一定程度的扩展性
    适配器虽然不是说是什么万能遥控,但还是要保持一定的连续性的扩展性,不能一个简单的问题也要重构

四、实例

看一个数据库相关的适配器的例程:

// 适配器接口
class IDbAdapter {
public:
    virtual ~IDbAdapter() = default;
    virtual bool connect(const std::string& host, const std::string& user, 
                        const std::string& password,const std::string& database) = 0;
    
    virtual bool disconnect() = 0; 
    virtual bool resultQuery(const std::string& query) = 0;
};
//MYSQL

class MySQLAdapter : public IDbAdapter {
private:
    ConnectionMySql conn_;
    //略
    
public:
    bool connect(const std::string& host,  const std::string& user, 
                const std::string& password,const std::string& database) override {
                //MYSQL数据库的连接代码,此处略
        return success;
    }
    
    bool disconnect() override {
       //MYSQL数据库的断开连接代码,此处略
        return true;
    }
    
    bool resultQuery(const std::string& query) override {
        //MYSQL数据库的查询代码,此处略
        
        return true;
    }
};
// SQLite

class SQLiteAdapter : public IDbAdapter {
private:
    SQLiteDn sqliteDb_;
    //略
    
public:
    bool connect(const std::string& host, const std::string& user, 
                const std::string& password,const std::string& database) override {
        // SQLite的连接代码,略
        return success;
    }
    
    bool disconnect() override {
        // SQLite的断开连接代码,略
        return true;
    }
    
    bool resultQuery(const std::string& query) override {
        // SQLite的查询代码,略
        
        return true;
    }

};

上述代码中介一最简单的适配器实例说明,完整的代码并未全部附上。重点是为了说明适配器应用的机制。真正实现还需要更多的功能和异常处理需要增加。

五、总结

适配器正如社会上的“中介”,它可以起到信息匹配交流的效果。但不是所有的情况都需要中介的出现,这就是设计者需要自行把握的情况。既要增加软件设计上的灵活的扩展性,也要考虑隔离变化付出的代价。至于何去何从,总不能靠掷硬币来决定吧?这就需要设计者关于把握整体的需求,做出最合适的设计。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值