爲何工廠模式能夠解耦?why?

爲何工廠模式能夠解耦?上篇

 

一、聊聊解耦?

耦合:代碼之間的關聯關係稱爲耦合,具備強關聯關係的稱爲強耦合。mysql

解耦:解除代碼之間的關聯關係,使每一個業務代碼職責單一,目的明確,一般咱們在業務上稱爲解耦。spring

二、代碼示例

咱們以傳統的EJB開發模式爲例子,先不以框架展現,你們能夠看看一些改代碼難受的場景。sql

業務來了:我須要把一段數據保存到mysql數據庫中,按照分層邏輯實現(controller,service,dao)數據庫

Dao接口層:oracle

public interface UserDao {app

/**框架

* 保存的接口方法ide

*/sqlserver

void save();編碼

}

Dao的mysql實現:

public class UserDaoMysqlImpl implements UserDao {

@Override

public void save() {

System.out.println("保存mysql數據庫成功!");

}

}

Service接口層:

public interface UserService {

/**

* 業務接口保存方法

*/

void save();

}

Service的實現:

public class UserServiceImpl implements UserService {

//業務層調用數據dao層,這裏不解釋了

private UserDao userDao = new UserDaoMysqlImpl();

@Override

public void save() {

userDao.save();

}

}

Controller視圖層:

public class UserController {

private UserService userService = new UserServiceImpl();

public void save(){

userService.save();

}

}

很明顯,咱們已經實現了業務功能:保存一段數據進mysql數據庫

這個時候,你的產品經理說,客戶mysql壞了,剛裝了個oracle,你再改改吧?

而後你這個時候也就加個oracle,實際上不費時,需求咱們再補充下

如今需求:保存一段數據,能夠保存在mysql,也能夠保存在oracle

上面已經有mysql代碼了,咱們能夠知道,我須要增長個dao的實現,稱爲UserDaoOracleImpl

上代碼先:

public class UserDaoOracleImpl implements UserDao {

@Override

public void save() {

System.out.println("保存oracle數據庫成功!");

}

}

ok咱們還要改一個地方,就是UserServiceImpl,以前父類接口指向的子類引用要改爲oracle

public class UserServiceImpl implements UserService {

//業務層調用數據dao層,這裏不解釋了

// private UserDao userDao = new UserDaoMysqlImpl();

private UserDao userDao = new UserDaoOracleImpl();

@Override

public void save() {

userDao.save();

}

}

咱們發現,在目前的需求形式上,dao的擴展咱們是必定會須要改的,由於知足多態的特性,可是咱們增長一個dao層的某個業務,連service業務層代碼也要動,你想一想,若是業務層代碼達到了上千,即使你有了註釋,改了某一層,另外一層也要跟着改動,是否是很難受?

因此咱們目前要解決:(若是每次dao進行擴展都去service修改源碼來切換到新的dao,這樣作法耦合度過高,每次都須要去修改UserServiceImpl的代碼)

這個場景,咱們很經典的稱爲耦合!!!!咱們能夠本身給耦合多一個定義

耦合:代碼之間的關聯關係稱爲耦合,更具體的說,在當前主流的職責劃分層次(controller,service,dao)明確的前提下進行編碼,某一層的改動,會致使另外一個層跟着變更,能夠稱爲耦合。

三、工廠模式能夠解耦

在不瞭解工廠模式的前提下,就默認把這個做爲生產對象的地方;

咱們新建一個工廠,稱爲BeanFactory

/**

* 定義一個bean工廠,專門生產普通對象

*/

public class BeanFactory {

public static UserDao getBean() {

return new UserDaoMysqlImpl();

}

}

而後咱們要對耦合的那一層修改,目前看是把service解耦了吧?我全部建立對象的操做,都在一個具體的工廠類裏;

public class UserServiceImpl implements UserService {

//業務層調用數據dao層,這裏不解釋了

// private UserDao userDao = new UserDaoMysqlImpl();

// private UserDao userDao = new UserDaoOracleImpl();

private UserDao userDao = BeanFactory.getBean();

@Override

public void save() {

userDao.save();

}

}

很明顯,我已經進行了service和dao解耦;可是!!!!!!

該死的需求是:我要改爲oracle,sqlserver,......

那咱們繼續:我順便把以前的getBean換成了mysql的

public class UserServiceImpl implements UserService {

//業務層調用數據dao層,這裏不解釋了

// private UserDao userDao = new UserDaoMysqlImpl();

// private UserDao userDao = new UserDaoOracleImpl();

// private UserDao userDao = BeanFactory.getMysqlBean();

private UserDao userDao = BeanFactory.getOracleBean();

@Override

public void save() {

userDao.save();

}

}

很明顯我如今已經把dao和service的耦合,轉移到了工廠和service上了,這就是解耦的一步;可是你們仍是疑惑,我感受我代碼增多了?或者更麻煩了?咱們繼續看

咱們每次增長新的業務,擴展,都要修改工廠,因此這個咱們能夠不能夠不在代碼裏直接作這個事情?--------引出配置文件

咱們在resources下定義一個applicationContext.properties

userDao=com.chenxin.gmall.user.demo.dao.UserDaoMysqlImpl

userService=com.chenxin.gmall.user.demo.service.UserServiceImpl

若是咱們須要換成oracle,咱們只改這個配置文件,改爲UserDaoOracleImpl,不須要去動代碼

那咱們剛剛的BeanFactory就又能夠經過讀取配置文件的方式,用反射來建立對象,反射建立對象是根據對象的全類名作的,不是直接new,看看效果

/**

* 定義一個bean工廠,專門生產普通對象

*/

public class BeanFactory {

private static Properties properties = new Properties();

//1.加載配置文件

static {

InputStream resourceAsStream = BeanFactory.class.getResourceAsStream("/applicationContext.properties");

try {

properties.load(resourceAsStream);

resourceAsStream.close();

} catch (IOException e) {

e.printStackTrace();

}

}

// public static UserDao getMysqlBean() {

// return new UserDaoMysqlImpl();

// }

//

// public static UserDao getOracleBean() {

// return new UserDaoOracleImpl();

// }

public static UserDao getBean(String key){

// 2.使用key得到value

String className = properties.getProperty(key);

// 3.使用value利用反射技術建立對象

try{

return (UserDao) Class.forName(className).newInstance();

}catch(Exception e){

e.printStackTrace();

return null;

}

}

}

好了,咱們來需求,咱們要保存到oracle,sqlserver數據庫,看看你是否是隻須要多一個dao的oracle實現,而後去改配置文件就ok?多一個sqlserver後,改下applicationContext.properties

算了我直接寫個代碼吧:

/**

* 新增了sqlserver的支持,多態的表現

*/

public class UserDaoSqlServerImpl implements UserDao {

@Override

public void save() {

System.out.println("保存SqlServer數據庫成功!");

}

}

改下applicationContext.properties

userDao=com.chenxin.gmall.user.demo.dao.UserDaoSqlServerImpl

userService=com.chenxin.gmall.user.demo.service.UserServiceImpl

你能夠試一下,是否是這麼幹的!

如今看來,是解耦了很多吧。可是會有人發現嗎,這個getBean返回值,是UserDao,若是你有不少,是否是咱們要寫不少不少的Dao的getBean?別急,後面一步一步帶你走向spring的思路

最後一句話,解耦不表明代碼必定少,更多時候是你用更多的代碼來解決人力成本,因此新手必定要記得,解耦的原則,是減小開發中出現的問題,增長開發效率,不表明代碼必定會減小下去,但願不要有這樣的誤區!

感謝閱讀,三連是最大的支持!

相關文章
相關標籤/搜索