Make application layer loosely coupled Make application layer loosely coupled spring spring

Make application layer loosely coupled


You approach is fine, it is look like some sort of Facade design pattern, but I would recommend more traditional way.

You already have spring as IoC container, so all you have to do is to extract interfaces from your *DBManager-classes and tell spring about your implementations. Then you will be able to inject an actual implementation using an interface, which in turn might resides in a totally different package. Therefore coupling will cease to exist.

Here is an example.

DataStorage contract:

package root;import java.util.List;public interface UserDataStorage {    void saveUserData(List<String> rows);}

DocumentStorage contract:

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

DataStorage implementation:

package root.domain;import org.springframework.stereotype.Service;import root.UserDataStorage;import java.util.List;@Servicepublic class MysqlDBManager implements UserDataStorage {    @Override    public void saveUserData(List<String> rows) {        System.out.println("Saving data....");    }}

DocumentStorage implementation:

package root.domain;import org.springframework.stereotype.Service;import root.UserDocumentStorage;@Servicepublic class MongoDBManager implements UserDocumentStorage {    @Override    public void saveUserDocs(String docs) {        System.out.println("Saving docs....");    }}

Then your service classes might look like this (please pay attention there is no reference to domain package:

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;@Servicepublic 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");    }}


IMHO there is a better way, The interfaces help you to have loosely couple layers, here is an example:

interface DocsDBManager {   void saveUserDocs(String docs);}interface UserDBManager {   void saveUserData(List<String> rows);}interface DBManager extends DocsDBManager, UserDBManager {}

And you must to implement them:

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

And:

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);       } }

And finally:

class Service {    @Autowired     private DBManager dBManager;    //....... code here    dBManager.saveUserData(rows);    dBManager.saveUserDocs(docs);}