使应用程序层松散耦合

时间:2017-10-10 07:48:39

标签: java spring oop design-patterns architecture

我有一个 Java Spring-boot 应用程序,它有图层():

  • 控制器(控制器类)
  • 服务(业务逻辑)
  • 域(数据库层)

在我的Domain里面我有两个数据库类

  • MysqlDBManager
  • MongoDBManager

我的service package中有很多课程,它们使用MysqlDBManagerMongoDBManager的方法。

我直接在我的服务类上使用MysqlDBManager' and MongoDBManager`的实例,然后 service 图层将紧密与图层耦合。

为了解决这个问题,我在包中创建了一个名为**DBManager**的类,它作为一个代理类,根据内部用例调用MysqlDBManager' and MongoDBManager`

现在服务层,而不是调用MysqlDBManager' and MongoDBManager directly they call DBManager , which internally calls MysqlDBManager'和MongoDBManager

因此,现在我的服务类与域层没有紧密结合。

以下是我的类,类似于我的用例。

MongoDBManager类:

 Class  MongoDBManager {
       public saveUserDocs(String docs) {
         //.....
       }
    }

MysqlDBManager类:

Class  MysqlDBManager {
       public saveUserData(List<String> rows) {
         //.....
       }
    }

DBManager类:

 Class  DBManager {

           @Autowired 
           private MysqlDBManager mysqlDBManager;
           @Autowired 
           private MongoDBManager mongoDBManager;

           public saveUserData(List<String> rows) {
             mysqlDBManager.saveUserData(rows);
           }

           public saveUserDocs(String docs) {
             mongoDBManager.saveUserDocs(docs);
           }
        }

服务类:

class Service {
    @Autowired 
    private DBManager dBManager;

    //....... code here
    dBManager.saveUserData(rows);
    dBManager.saveUserDocs(docs);
}

我的问题是

这是(如上所述)使我的应用程序层松散耦合的好方法,或者它们存在更好的方法吗?

2 个答案:

答案 0 :(得分:4)

恕我直言,有一种更好的方法,接口可以帮助你松散地耦合图层,这是一个例子:

interface DocsDBManager {
   void saveUserDocs(String docs);
}

interface UserDBManager {
   void saveUserData(List<String> rows);
}

interface DBManager extends DocsDBManager, UserDBManager {
}

你必须实施它们:

class  MongoDBManager implements DocsDBManager {
   public void saveUserDocs(String docs) {
     //.....
   }
}

class  MysqlDBManager implements UserDBManager {
   public void saveUserData(List<String> rows) {
     //.....
   }
}

class  DBManagerBase implements DBManager  {

       @Autowired 
       private DocsDBManager docsDBManager;
       @Autowired 
       private UserDBManager userDBManager;

       public void saveUserData(List<String> rows) {
            userDBManager.saveUserData(rows);
       }

       public void saveUserDocs(String docs) {
           docsDBManager.saveUserDocs(docs);
       }
 }

最后:

class Service {
    @Autowired 
    private DBManager dBManager;

    //....... code here
    dBManager.saveUserData(rows);
    dBManager.saveUserDocs(docs);
}

答案 1 :(得分:4)

你的方法很好,它看起来像某种Facade设计模式,但我会推荐更传统的方式。

你已经有了spring作为IoC容器,所以你要做的就是从你的*DBManager类中提取接口,然后告诉你实现的内容。然后,您将能够使用接口注入实际实现,而接口又可能位于完全不同的包中。因此,耦合将不复存在。

这是一个例子。

DataStorage合同:

package root;

import java.util.List;

public interface UserDataStorage {
    void saveUserData(List<String> rows);
}

DocumentStorage合同:

package root;

public interface UserDocumentStorage {
    void saveUserDocs(String docs);
}

DataStorage实施:

package root.domain;

import org.springframework.stereotype.Service;
import root.UserDataStorage;

import java.util.List;

@Service
public class MysqlDBManager implements UserDataStorage {
    @Override
    public void saveUserData(List<String> rows) {
        System.out.println("Saving data....");
    }
}

DocumentStorage实施:

package root.domain;

import org.springframework.stereotype.Service;
import root.UserDocumentStorage;

@Service
public class MongoDBManager implements UserDocumentStorage {
    @Override
    public void saveUserDocs(String docs) {
        System.out.println("Saving docs....");
    }
}

然后您的服务类可能如下所示(请注意,没有对domain包的引用:

package root.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import root.UserDataStorage;
import root.UserDocumentStorage;

import java.util.Collections;

@Service
public class MyService {

    private final UserDataStorage dataStorage;
    private final UserDocumentStorage documentStorage;

    @Autowired
    public MyService(UserDataStorage dataStorage, UserDocumentStorage documentStorage) {
        this.dataStorage = dataStorage;
        this.documentStorage = documentStorage;
    }

    public void callMe() {
        this.dataStorage.saveUserData(Collections.emptyList());
        this.documentStorage.saveUserDocs("Document1");
    }
}