跨越时空的融合!如何用适配器模式整合早期业务系统?

417 阅读5分钟

最近接到了一个项目需求,需要整合过去7年,8个系统,前端重新开发以及唯护,但是这些业务系统都有各自的接口格式和token令牌,但是我们需要把它们整合成一个统一的接口格式和token形式,供前端调用。

在这个场景中,我们可以使用适配器模式来解决问题。适配器模式可以将一个类的接口转换成客户希望的另外一个接口,从而使原本由于接口不兼容而无法在一起工作的类可以一起工作。

在这个场景中,我们可以将每个早期业务系统的接口作为一个被适配的对象,而我们需要整合成的统一接口格式则作为目标对象。我们可以创建一个适配器来实现这一转换,使得所有早期业务系统的接口都可以转换为我们需要的统一接口格式。

首先,我们可以创建一个适配器函数,该函数接受一个早期业务系统的接口对象,并将其转换为我们需要的统一接口格式。下面是一个示例代码:

function Adapter(oldInterface) {
  return {
    getToken() {
      return oldInterface.token;
    },
    getData() {
      const data = oldInterface.data;
      const newData = {
        id: data.id,
        name: data.name,
        email: data.email,
        age: data.age,
        address: data.address,
      };
      return newData;
    },
  };
}

上面的代码中,我们定义了一个Adapter函数,它接受一个早期业务系统的接口对象oldInterface作为参数,并返回一个新的适配后的对象,该对象包含getToken和getData两个方法。

在getToken方法中,我们返回了早期业务系统的token令牌,以适配我们的统一接口格式。

在getData方法中,我们将早期业务系统的数据转换为我们需要的统一接口格式。具体地,我们提取了数据对象中的id、name、email、age和address属性,并将它们组合成一个新的数据对象。

接下来,我们可以使用这个适配器函数来适配所有的早期业务系统的接口对象,并将它们转换为我们需要的统一接口格式。示例代码如下:

// 定义旧接口1
const oldInterface1 = {
  token: 'abc123',
  data: {
    id: '001',
    name: '张三',
    email: 'zhangsan@example.com',
    age: 25,
    address: '北京市海淀区',
  },
};

// 定义旧接口2
const oldInterface2 = {
  auth: 'Bearer abc123',
  payload: {
    userID: '002',
    userName: '李四',
    userEmail: 'lisi@example.com',
    userAge: 28,
    userAddress: '上海市徐汇区',
  },
};

// 定义适配器函数
function Adapter(oldInterface) {
  return {
    getToken: function() {
      if (oldInterface.token) {
        return oldInterface.token;
      } else if (oldInterface.auth) {
        return oldInterface.auth.split(' ')[1];
      }
    },
    getData: function() {
      if (oldInterface.data) {
        return oldInterface.data;
      } else if (oldInterface.payload) {
        return {
          id: oldInterface.payload.userID,
          name: oldInterface.payload.userName,
          email: oldInterface.payload.userEmail,
          age: oldInterface.payload.userAge,
          address: oldInterface.payload.userAddress,
        };
      }
    },
  };
}

// 适配旧接口1并输出统一接口1
const adapter1 = Adapter(oldInterface1);
const unifiedInterface1 = {
  token: adapter1.getToken(),
  data: adapter1.getData(),
};
console.log(unifiedInterface1); // { token: 'abc123', data: { id: '001', name: '张三', email: 'zhangsan@example.com', age: 25, address: '北京市海淀区' } }

// 适配旧接口2并输出统一接口2
const adapter2 = Adapter(oldInterface2);
const unifiedInterface2 = {
  token: adapter2.getToken(),
  data: adapter2.getData(),
};
console.log(unifiedInterface2); // { token: 'abc123', data: { id: '002', name: '李四', email: 'lisi@example.com', age: 28, address: '上海市徐汇区' } }

在使用适配器模式解决场景问题的同时,可以结合使用其他设计模式来进一步优化代码,提高系统的可维护性和可扩展性。

例如,在Vue项目中,可以结合使用工厂模式来创建适配器对象,以更好地管理不同的适配器,并且方便后续新增适配器。

在具体实现上,可以将适配器对象存储在一个对象池中,每次需要使用时从对象池中获取相应的适配器对象,避免重复创建。同时,在工厂模式中可以使用单例模式,确保只有一个适配器工厂对象,避免重复创建和管理。

以下是一个简单的示例代码:

// 定义适配器工厂类
class AdapterFactory {
  constructor() {
    if (!AdapterFactory.instance) {
      this.adapters = {}; // 适配器对象池
      AdapterFactory.instance = this;
    }
    return AdapterFactory.instance;
  }

  // 获取适配器对象
  getAdapter(type) {
    if (!this.adapters[type]) {
      switch (type) {
        case 'type1':
          this.adapters[type] = new AdapterType1();
          break;
        case 'type2':
          this.adapters[type] = new AdapterType2();
          break;
        // ...
        default:
          throw new Error(`Invalid adapter type: ${type}`);
      }
    }
    return this.adapters[type];
  }
}

// 定义适配器接口
class Adapter {
  constructor(data) {
    this.data = data;
  }

  // 处理数据
  processData() {
    throw new Error('processData method is not implemented');
  }
}

// 定义具体适配器类
class AdapterType1 extends Adapter {
  processData() {
    // 处理type1数据
    // ...
    return {
      // 返回适配后的数据格式
    };
  }
}

class AdapterType2 extends Adapter {
  processData() {
    // 处理type2数据
    // ...
    return {
      // 返回适配后的数据格式
    };
  }
}

// 使用适配器工厂获取适配器对象,并调用适配器的processData方法
const factory = new AdapterFactory();
const adapter1 = factory.getAdapter('type1');
const adapter2 = factory.getAdapter('type2');
const data1 = adapter1.processData(data1FromApi);
const data2 = adapter2.processData(data2FromApi);

// 在Vue项目中,可以将适配器工厂对象作为全局变量挂载在Vue.prototype上,方便在组件中调用
Vue.prototype.$adapterFactory = new AdapterFactory();

适配器模式是一种结构型设计模式,它可以将一个类的接口转换成客户希望的另外一个接口,从而使原本由于接口不兼容而无法在一起工作的类可以一起工作。适配器模式主要由三个部分组成:被适配的对象、目标对象和适配器。

被适配的对象是指原本无法兼容的接口。目标对象是指客户希望使用的接口格式。适配器是一个中间件,它可以将被适配的对象转换为目标对象。

适配器模式的优点包括:

  • 可以让原本无法兼容的对象一起工作,提高代码的复用性和可维护性;
  • 可以降低系统的耦合度,使得系统更加灵活和易于扩展;
  • 可以隐藏系统内部的实现细节,保护系统的安全性。

适配器模式的缺点包括:

  • 适配器需要额外的开发成本,增加了代码的复杂度;
  • 适配器需要额外的运行开销,可能会降低系统的性能;
  • 如果适配器实现不当,可能会导致系统出现不可预测的错误。

适配器模式在解决接口兼容性问题上非常有效,特别是在整合多个系统的场景中,可以大大提高代码的可维护性和可扩展性。