用于不同存储的抽象层

时间:2017-06-28 05:04:18

标签: mongodb amazon-s3 amazon-dynamodb abstraction

我需要构建一个抽象层来存储我们的应用程序。数据将保存在dynamoDB,S3,Mongo或Mysql中(这可能会改变)。我们的应用程序将收到GET和POST请求。应用程序将触及抽象层,该层应决定当前使用的数据存储是什么,并应保存或从当前存储中获取数据。我们应该可以灵活地在任何时候更改存储,只需对代码进行最小的更改。设计这个抽象层的最佳方法是什么?

1 个答案:

答案 0 :(得分:2)

这是典型的策略和工厂设计模式。

您将拥有抽象Storage,并且您要实施的任何内容都将遵循相同的合同(例如MongoDBStorageCassandraStorage)。

我实际上会创建NoSQLStorageRelationalStorage作为单独的抽象,但在相同的Storage下,因为它们的数据结构可能不同,因为关系中的One to Many表大多数时间只变为一个NoSQL中的表/集合。这可能会增加非常不受欢迎和不必要的复

同样,S3与Relational或NonRelational的存储不同,我会毫不犹豫地用一把刀解决所有类型的问题。 (但为了简单起见,我假设他们接受类似的输入。

在每个策略的内部,您必须包装实际的存储API,并简单地将输入转换为实际存储API支持的输入。例如,您必须为MongoDB将StorageRecord翻译为DBObject

设计非常粗略,如下所示,我使用scala lang进行设计,你绝对可以使用任何OO lang。

将向客户提供的存储抽象

trait Storage {
  def insert(record: StorageRecord): Boolean
  def query(query: Query): List[StorageRecord]
  def update(updateCondition: Query, updateQuery: Query)
  def delete(deleteCondition: Query)
}

trait RelationalStorage extends Storage

trait StorageRecord
trait Query

trait NoSQLStorage extends Storage

<强>实现

class MongoDBStorage extends NoSQLStorage {
  override def insert(record: StorageRecord): Boolean = ???

  override def query(query: Query): List[StorageRecord] = ???

  override def update(updateCondition: Query, updateQuery: Query): Unit = ???

  override def delete(deleteCondition: Query): Unit = ???
}

class DynamoDBStorage extends NoSQLStorage {
  override def insert(record: StorageRecord): Boolean = ???

  override def query(query: Query): List[StorageRecord] = ???

  override def update(updateCondition: Query, updateQuery: Query): Unit = ???

  override def delete(deleteCondition: Query): Unit = ???
}

客户将调用的StorageFactory获得正确的Storage

class NoSQLStorageFactory {

  def getStorage(config: String): Storage = {
    config match {
      case "MongoDB" => new MongoDBStorage
      case "DynamoDB" => new DynamoDBStorage
      case _ => throw new Exception("Storage not configured")
    }
  }
}

客户端代码如下所示,您可以将存储服务器,数据库名称,存储驱动程序作为可配置属性,只需更改配置即可使其正常工作。

val storage = applicationConfig.get("storage.driver")
val storage = new NoSQLStorageFactory().getStorage(storage)
storage.insert(instanceOfYourStorageRecord)