服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

从重构的角度学习bridge设计模式


  从重构的角度学习bridge设计模式

  bridge模式是一个在实际系统中经常应用的模式。它最能体现设计模式的原则针对接口进行编程,和使用聚合不使用继承这两个原则。

  由于我们过分的使用继承,使类的结构过于复杂,不易理解,难以维护。特别是在java中由于不能同时继承多个类,这样就会造成多层继承,维护更难。

  bridge模式是解决多层继承的根本原因。如果你在实现应用中一个类,需要继承两个以上的类,并且这两者之间又持有某种关系,它们两个都会有多种变化。

  bridge模式是把这两个类,分解为一个抽象,一个实现,使它们两个分离,这样两种类可以独立的变化。

  抽象就是,把一个实体的共同概念(相同的步骤),抽取出来(分解出几个相互独立的步骤),作为一个过程。如我们把数据库的 操作抽象为一个过程,有几个步骤,创建sql语句,发送到数据库处理,取得结果。

  实现就是怎样完成这个抽象步骤,如发送到数据库,需要结合具体的数据库,考虑怎样完成这个步骤等。并且同一步骤可能存在不同的实现,如对不同的数据库需要不同的实现。

  现在我们假设一个情况,也是web中经常遇到的,在一个page有输入框,如客户信息的姓名,地址等,输入信息后,然后按查找按钮,把查找的结果显示出来。

  我们现在假设查找客户信息和帐户信息,它们在不同的表中。

  但是我们的系统面对两种人群,总部的它们信息保存到oracle数据库,但是各个分公司的数据保存在sybase中,数据库的位置等各不相同,这两种的操作不同。

  下面是我们一般首先会使用的方式,使用if else进行,判断,这样使用系统难以维护,难以扩展,不妨你增加一种查询,或者一种数据库试试?

public class searchaction(){
public vector searchdata(string actiontype,string dbtype){
string sql="";
if(actiontype.equal("查找客户信息")){
//如果是查询客户信息,拼sql语句从客户表中读取数据
sql="select * from customer "

if(dbtype.equal("oracle")){
//从总部数据库读取,数据库为oracle
string connect_string ="jdbc:oracle:thin:hr/hr@localhost:1521:hrdb";
drivermanager.registerdriver (new oracle.jdbc.oracledriver());
connection conn = drivermanager.getconnection (connect_string);
// create a statement
statement stmt = conn.createstatement ();
resultset rset = stmt.executequery (sql);
//以下省略部分动态从数据库中取出数据,组装成vector,返回
..................................
...................................
}else(dbtype.equal("sybase")){
//从分公司数据库读取,数据库为sybase
string connect_string ="jdbc:sybase:tds:cai/cai@192.168.1.12:1521:fin";
drivermanager.registerdriver (new com.sybase.jdbc.sybdriver());
connection conn = drivermanager.getconnection (connect_string);
// create a statement
statement stmt = conn.createstatement ();
resultset rset = stmt.executequery (sql);
//以下省略部分动态从数据库中取出数据,组装成vector,返回
..................................
...................................

}

}else if(actiontype.equal("查找帐户信息")){
//如果是查询帐户信息,拼接sql语句从帐户表中读取数据
sql="select * from account "
if(dbtype.equal("oracle")){
..........................
..........................
(作者注:此处省略从oracle读取,约300字)

}else if(dbtype.equal("sybase")){
..........................
..........................
(作者注:此处省略从sybase读取,约300字)
}

}
}
}

  如果你认为这写的比较弱智,应该进行使用函数,但是你也会大量使用if else。


  于是我们进行重构,首先我们学习过dao模式,就是把数据读取进行分里,我们定义一个共同的接口,它负责数据库的操作,然后根据不同的数据库进行实现,在我们的查询操作中,使用接口,进行操作,这样就可以不用考虑具体的实现,我们只管实现过程。

  查询共同接口:

public interface searchdb{
public vector searchfromdb(string sql)
}
oracle数据库的查询实现
public class searchdboracleimpl{
public vector searchfromdb(string sql){
//从总部数据库读取,数据库为oracle
string connect_string ="jdbc:oracle:thin:hr/hr@localhost:1521:hrdb";
drivermanager.registerdriver (new oracle.jdbc.oracledriver());

resultset rset = stmt.executequery (sql);
.............................
............................

}
}
sybase数据库的查询实现
public class searchdbsysbaseimpl{
public vector searchfromdb(string sql){
//从分公司数据库读取,数据库为sysbase
string connect_string ="jdbc:sybase:tds:cai/cai@192.168.1.12:1521:fin";
drivermanager.registerdriver (new com.sybase.jdbc.sybdriver());
resultset rset = stmt.executequery (sql);
.............................
............................

}
}

  这样在我们的查询中就可以使用接口searchdb,但是创建有是一个问题,因为我们不能静态的确定,查询的数据库类型,必须动态确定,于是我们又想到使用简单工厂方法,来分别创建这里的具体实现,根据类别,创建

public class searchfactory{
public static searchdb createsearch(int dbtype){
if(dbtype.equal("oracle")){
return searchdboracleimpl();
}else if(dbtype.equal("sybase")){
return searchdbsysbaseimpl();
}
}
}
于是我们的查询代码可以改变为这样了;
public class searchaction(){

public vector searchdata(string actiontype,string dbtype){
string sql="";
if(actiontype.equal("查找客户信息")){
//如果是查询客户信息,拼sql语句从客户表中读取数据
sql="select * from customer "
searchdb obj=searchfactory.createsearch(dbtype);
return obj.searchfromdb(sql);

}else if(actiontype.equal("查找帐户信息")){
//如果是查询帐户信息,拼接sql语句从帐户表中读取数据
sql="select * from account "
searchdb obj=searchfactory.createsearch(dbtype);
return obj.searchfromdb(sql);
}
}
}

  是不是简单一些,如果增加一个新的数据库,对我们只需增加一个新的数据库实现便可,老的代码,不需改变,这样便实现开-闭原则(open-closed原则),在我们的查询查询中使用的是接口,这就是设计模式的原则,针对接口进行编程,并且使用聚合,而不是直接的继承大家,可以考虑使用继承来完成该工作怎样实现。上面是把实现进行分离,实现可以动态变化!

  我们把查询的操作的具体数据库实现进行了分离,增强了灵活性,但是我们的查询。仍然使用了if else这样仍然不易进行扩展,于是我们进行抽象一个查询操作的过程,把它分成几个具体步骤,创建sql语句,发送到数据库,执行查询,返回结果。

  它们虽然是不同的查询,sql各不相同,不同数据库执行不同,返回结果的内容不同。但是这个过程却是不变的,于是我们声明一个抽象类,来完成这个过程。

public abstract class searchaction{
searchdb obj;
//两个步骤
public searchdb createsearchimple(int dbtype){
return searchfactory.createsearch(dbtype);
}
public abstract string createsql();

//查询过程,最后返回结果
public vector searchresult(int dbtype){
obj=createsearchimple(dbtype);
return obj.searchfromdb(createsql())
}
}

//我们客户查询,操作
public class searchcustomeraction{
public string createsql(){
return "select * from customer"
}
}
//我们的帐户查询操作
public class searchaccountaction{
public string createsql(){
return "select * from account"
}
}

  这样我们的查询编程简单的创建sql语句,我们应该再创建一个工厂方法,来完成创建它们

public class actionfactory{
public static searchaction ceateaction(int actiontype){
if(actiontype.equal("customer")){
return searchcustomeraction();
}else if(actiontype.equal("account")){
return searchaccountaction();
}
}
}

  这样我们把查询操作的过程进行了抽象,定义了步骤,和具体过程,经过我们的两次改变把抽象部分和实现部分进行分离,使他们都可以独立的变化,增强灵活性。

  我们再看当初查询实现,现在经过这两次的地修改,变成了什么模样?如下:

public class searchaction(){
public vector searchdata(string actiontype,string dbtype){
searchaction action=actionfactory.ceateaction(actiontype);
return action.searchresult(dbtype);
}

扫描关注微信公众号