前言:笔者在最开始写程序的时候经常会遇到一种情况,例如更改一个字段、或者添加一种小功能,就要把原来写过的东西几乎废弃掉,或者更改大量以前写过的代码。又或者自己写的东西时间久了再去回顾,完全找不到到时为什么这么写的头绪,如果遇到了Bug更是无法快速定位在哪里小范围出现的问题。如果你也经常遇到这种问题,就说明你现阶段非常需要学习下设计模式了。
在网上经常说的设计模式有23种,也有一些更多的设计模式,无非也是从这些设计模式中变种而来。如果让笔者来形容什么是设计模式,我认为设计模式是:一种思想,一种模式,一种套路,一种解决问题的高效策略。
有说的不正确或者不准确的地方欢迎留言指正
有什么有趣的写作技巧或者想法欢迎大家给我留言,大家的帮助是我写下去最有效的动力
在项目后期维护我们会遇到一种情况,就是在添加一些第三方功能时会遇到接口不同的情况,更改现在系统的接口或者改动第三方接口都有可能造成破坏原有结构、造成不必要的BUG出现的风险,而且也违背了开闭原则。这时我们就可以考虑今天笔者要跟大家介绍的《适配器模式》了
适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
今天的示例以数据库的增删改查为例子展示
在项目之初,我们准备接入两种数据库Mysql与Oracle,而且对应的增删改查的接口也是一直的。
public interface IHelper
{
void Add<T>();
void Delete<T>();
void Update<T>();
void Query<T>();
}
public class MysqlHelper : IHelper
{
public void Add<T>()
{
this.Log($"This is {GetType().Name} Add");
}
public void Delete<T>()
{
this.Log($"This is {GetType().Name} Delete");
}
public void Update<T>()
{
this.Log($"This is {GetType().Name} Update");
}
public void Query<T>()
{
this.Log($"This is {GetType().Name} Query");
}
}
public class OracleHelper : IHelper
{
public void Add<T>()
{
this.Log($"This is {GetType().Name} Add");
}
public void Delete<T>()
{
this.Log($"This is {GetType().Name} Delete");
}
public void Update<T>()
{
this.Log($"This is {GetType().Name} Update");
}
public void Query<T>()
{
this.Log($"This is {GetType().Name} Query");
}
}
现在随着项目的需求,我们需要接入RedisHelper,但是它对应的增删改查的接口和项目中的不一样
public class RedisHelper
{
public void AddRedis<T>()
{
this.Log($"This is {GetType().Name} Add");
}
public void DeleteRedis<T>()
{
this.Log($"This is {GetType().Name} Delete");
}
public void UpdateRedis<T>()
{
this.Log($"This is {GetType().Name} Update");
}
public void QueryRedis<T>()
{
this.Log($"This is {GetType().Name} Query");
}
}
这时我们就可以使用适配器模式了。适配器模式有两个分类《类适配器模式》和《对象适配器模式》
类适配器模式
public class RedisHelperClass : RedisHelper, IHelper
{
public void Add<T>()
{
base.AddRedis<T>();
}
public void Delete<T>()
{
base.DeleteRedis<T>();
}
public void Update<T>()
{
base.UpdateRedis<T>();
}
public void Query<T>()
{
base.QueryRedis<T>();
}
}
对象适配器模式
public class RedisHelperObject : IHelper
{
private RedisHelper redisHelper = null;
public RedisHelperObject(RedisHelper redisHelper)
{
this.redisHelper = redisHelper;
}
public void Add<T>()
{
this.redisHelper.AddRedis<T>();
}
public void Delete<T>()
{
this.redisHelper.DeleteRedis<T>();
}
public void Update<T>()
{
this.redisHelper.UpdateRedis<T>();
}
public void Query<T>()
{
this.redisHelper.QueryRedis<T>();
}
}
调用如下
void Start()
{
IHelper helper = new MysqlHelper();
helper.Update<AdapterComponent>();
helper = new OracleHelper();
helper.Update<AdapterComponent>();
helper = new RedisHelperClass();
helper.Update<AdapterComponent>();
helper = new RedisHelperObject(new RedisHelper());
helper.Update<AdapterComponent>();
}
是不是很简单呢,只是在需要在适配的类上嵌套一个类就变成了一个设计模式----适配器模式。。。。。
不过在使用适配器的时候还是有注意的地方的,下面说一下注意点
类适配器和对象适配器,笔者更倾向于对象适配于,因为组合优于继承,那么优在哪里呢?第一,通过构造传入指定需要适配的类型,我们就不会把这个适配的类型写死,后面如果有更改我们更方便调整。第二,根据里氏替换我们知道,使用对象适配器不会暴露父类需要适配者中的内容,封装性更好。
要在双方都不太容易修改的时候在使用适配器模式进行适配。如果在项目的设计之初,这种接口不同的情况就需要避免掉。适配器就像一个补丁,在后期没有办法的时候就行弥补,而不是只要接口不一样就使用适配器模式。