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

原创 2003年06月09日 07:36:00
从重构的角度学习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);
}
现在假如增加一个数据库类型,将会改变那些??,如果增加一种查询操作需要改变那些???

讨论点:
1:在我们的重构过程中,
怎样使用设计模式原则的???
现在如果增加功能,遵循开闭原则吗??
2:我们使用了两个简单工厂,这是为了简化,一般最好使用抽象工厂方法,
如果改为抽象工厂,怎样修改???



我打算写一系列的文章介绍设计模式,
希望从重构的角度考虑模式的应用,而不是
直接介绍模式,这样对初学者容易入门,step by step。
如果在自己的代码中遇到类似的情景,可以进行重构。


从重构学习proxy,预告
为什么EJB有Home,remote,bean这三种角色?
为什么又客户端与容器进行交互??
介绍在EJB中的应用???

从重构学习decorator??

模式识别/机器学习百题(含大部分答案)

一、概论1、简述模式的概念和它的直观特性,解释什么是模式识别,同时绘出模式识别系统的组成框图,并说明各部分的主要功能特性。对于存在于时间和空间中,可观察的物体,如果我们可以区分它们是否相同或相似,都可...
  • withchris
  • withchris
  • 2017年03月16日 11:36
  • 1423

深度学习参数和架构设计技巧

深度学习性能提升的诀窍 Pedro Ribeiro Simoes拍摄 原文: How To Improve Deep Learning Performance 作者: Jason Brownle...
  • zyqdragon
  • zyqdragon
  • 2017年04月30日 20:23
  • 1401

设计模式(结构型)之桥接模式(Bridge Pattern)

桥接模式是一种很实用的结构型设计模式,如果软件系统中某个类存在多个独立变化的维度,通过该模式可以将这多个维度分离出来,使他们可以独立扩展,让系统更加符合“单一职责原则”。与多层继承方案不同,它将多个独...
  • yanbober
  • yanbober
  • 2015年04月29日 21:15
  • 3284

设计模式Bridge学习

  • 2008年06月16日 11:22
  • 190KB
  • 下载

从哲学角度学习设计模式-抽象工厂

  • 2007年06月28日 09:45
  • 4KB
  • 下载

设计模式C++学习笔记之十一(Bridge桥梁模式)

转自 : http://www.cnblogs.com/wanggary/archive/2011/04/17/2019067.html 桥梁模式,将抽象部分与它的实现部分分离,使它...
  • xiaoxianerqq
  • xiaoxianerqq
  • 2016年05月06日 10:33
  • 162

设计模式学习笔记十二:桥接模式(Bridge Pattern)

设计模式学习笔记十二:桥接模式(Bridge Pattern)     1.概述     桥接模式(Bridge),将抽象部分与它的实现部分分离,是他们都可以独立的变化。什么叫抽象与它的实现分...
  • AlbenXie
  • AlbenXie
  • 2017年08月11日 12:27
  • 151

设计模式之Bridge模式学习

问题: 面向对象的需要解决的问题为:松耦合和高内聚;追求的目标是尽可能的提高系统模块内部的内聚,尽可能降低模块间的耦合;但这也是在面向对象设计过程中最为难把握的部分,大家肯定在OO的过程中遇到这样的...
  • cheng7068
  • cheng7068
  • 2013年01月14日 13:45
  • 310

Java学习之道:java设计模式—Bridge模式

一、引子 下面是吕振宇大牛的一个例子,个人觉得挺好的,有助于理解Bridge模式的设计目的: 设想要绘制一幅图画,蓝天、白云、绿树、小鸟,如果画面尺寸很大,那么用蜡笔绘制就会遇到点麻烦。毕竟细细的...
  • u011511429
  • u011511429
  • 2013年07月27日 14:40
  • 724

设计模式C++学习笔记之十一(Bridge桥梁模式)

设计模式C++学习笔记之十一(Bridge桥梁模式) 桥梁模式,将抽象部分与它的实现部分分离,使它们都可以独立地变化。实现分离的办法就是增加一个类, 11.1.解释 main(),客户 I...
  • xueer2014
  • xueer2014
  • 2015年01月14日 15:42
  • 97
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:从重构的角度学习bridge设计模式
举报原因:
原因补充:

(最多只允许输入30个字)