桥接模式深入.docx
- 文档编号:4439122
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:11
- 大小:62.76KB
桥接模式深入.docx
《桥接模式深入.docx》由会员分享,可在线阅读,更多相关《桥接模式深入.docx(11页珍藏版)》请在冰豆网上搜索。
桥接模式深入
12.5 桥接模式(Bridge)
本节从以下几个方面来详细讲解桥接模式:
Ø 桥接模式的核心思想。
Ø 何时使用桥接模式。
Ø 在Java中的应用—JDBC桥DriverManager。
12.5.1 桥接模式的核心思想
桥接模式是软件设计模式中最复杂的模式之一,它把事物对象和其具体行为、具体特征分离开来,使它们可以各自独立的变化。
桥接模式的用意是将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立变化。
这句话有3个关键词,也就是抽象化、实现化和脱耦。
Ø 抽象化:
存在于多个实体中的共同的概念性联系,就是抽象化。
作为一个过程,抽象化就是忽略一些信息,从而把不同的实体当做同样的实体对待。
Ø 实现化:
抽象化给出的具体实现,就是实现化。
Ø 脱耦:
所谓耦合,就是两个实体的行为的某种强关联。
而将它们的强关联去掉,就是耦合的解脱,或称脱耦。
在这里,脱耦是指将抽象化和实现化之间的耦合解脱开,或者说是将它们之间的强关联转换成弱关联。
将两个角色之间的继承关系改为聚合关系,就是将它们之间的强关联转换成为弱关联。
因此,桥接模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以相对独立变化,这就是桥接模式的用意。
桥接模式所涉及的角色如下。
Ø 抽象化(Abstraction)角色—桥接类:
抽象化给出的定义,并保存一个对实现化对象的引用。
Ø 修正抽象化(RefinedAbstraction)角色—桥接具体类:
扩展抽象化角色,改变和修正父类对抽象化的定义。
Ø 实现化(Implementor)角色—目标接口:
这个角色给出实现化角色的接口,但不给出具体的实现。
必须指出的是,这个接口不一定与抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。
实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作的更高一层的操作。
Ø 具体实现化(ConcreteImplementor)角色—目标实现类:
这个角色给出实现化角色接口的具体实现。
如图12-21所示就是一个实现了桥接模式的示意性系统的结构图。
图12-21 桥接模式结构图
图中的Client就可以通过Bridge桥来实现对Sourcable实现类的操作了。
下面来看具体的实现。
(1)Sourcable类的源代码如程序12-39所示,它定义了两个操作函数。
程序12-39 源接口Sourcable.java
packagestructure.adapter;
/**
*@authorliuzhongbing
*源接口
*/
publicinterfaceSourcable{
publicvoidoperation();
}
(2)SourceSub1实现了Sourcable接口,实现函数operation()负责输出一个字符串。
其源代码如程序12-40所示。
程序12-40 源接口的实现子类SourceSub1.java
packagestructure.adapter;
/**
*@authorliuzhongbing
*源接口的实现类
*/
publicclassSourceSub1extendsDefaultWrapper{
publicvoidoperation(){
System.out.println("源接口的一个实现子类Sub1");
}
}
(3)SourceSub2实现了Sourcable接口,实现函数operation()负责输出一个字符串。
其源代码如程序12-41所示。
程序12-41 源接口的实现子类SourceSub2.java
packagestructure.adapter;
/**
*@authorliuzhongbing
*源接口的实现类
*/
publicclassSourceSub2extendsDefaultWrapper{
publicvoidoperation(){
System.out.println("源接口的一个实现子类Sub2");
}
}
(4)桥接类Bridge是一个抽象类,它拥有一个Sourcable对象,并可以通过getter/setter来设置该对象。
其源代码如程序12-42所示。
程序12-42 桥接类Bridge.java
packagestructure.bridge;
/**
*@authorAdministrator
*桥接模式抽象类
*/
publicabstractclassBridge{
privateSourcablesource;
publicSourcablegetSource(){
returnsource;
}
publicvoidsetSource(Sourcablesource){
this.source=source;
}
publicvoidoperation(){
source.operation();
}
}
(5)桥接具体类MyBridge是一个Bridge的具体实现,它拥有自己的实现。
其源代码如程序12-43所示。
程序12-43 桥接具体类MyBridge.java
packagestructure.bridge;
/**
*@authorAdministrator
*桥接具体类
*/
publicclassMyBridgeextendsBridge{
publicvoidoperation(){
getSource().operation();
}
}
以上我们编写了两个实现SourceSub1和SourceSub2,下面我们便可以通过Bridge桥来实现对它们的调用。
首先创建一个桥对象,然后分别给该桥设置不同的目标对象source1和source2,然后调用桥的operation()即可实现对两个目标的调用。
其源代码如程序12-44所示。
程序12-44 测试类Client.java
packagestructure.bridge;
publicclassClient{
publicstaticvoidmain(String[]args){
//创建桥对象
Bridgebridge=newMyBridge();
//调用第一个对象
Sourcablesource1=newSourceSub1();
bridge.setSource(source1);
bridge.operation();
//调用第二个对象
Sourcablesource2=newSourceSub2();
bridge.setSource(source2);
bridge.operation();
}
}
运行该程序的结果如下:
源接口的一个实现子类Sub1
源接口的一个实现子类Sub2
从输出的结果可以看出,通过Bridge桥实现了对目标类的调用。
12.5.2 何时使用桥接模式
从以上的讲解可以看出,桥接模式与前面几种模式都很相似,但是它们应用的目的和场景不同:
Ø 适配器用于将一个类改变为另一个接口,桥接模式是将抽象化与实现分离,使得两者接口不同。
Ø 装饰器模式是把一个类扩展功能再转化为同一个接口,而桥接模式是将一个类转化为另一个类来控制。
Ø 代理模式是为一个类提供一个统一的代理类,完全可以不操作被代理的类;桥接模式也是提供了一个桥接类,但需要使用该桥接类来进行目标对象的操作。
Ø 外观模式是为一系列的类提供一个统一的外观类,完全可以不操作被代理的类;桥接模式也是提供了一个桥接类,但需要使用该桥接类来进行目标对象的操作。
由此可见,桥接模式与前面几种模式都很相似,这是应用的角度不同。
它只有在一个系统中拥有更多的抽象化和实现化角色时才使用,目的是为了增加互相操作的灵活性。
12.5.3 在Java中的应用—JDBC桥DriverManager
桥梁模式的关键是找出抽象化角色和具体化角色。
典型应用是JDBC应用,JDBCAPI属于抽象化角色,而driver则属于具体化角色,其中需要通过一个DriverManager类根据指定URL得到具体实现。
如图12-22所示,DriverManager就为我们提供了一个桥,通过这个桥可以实现对各种数据库驱动的加载。
图12-22 JDBC桥DriverManager
因为有了DriverManager桥,我们才可以像下面这样方便地连接各种数据源。
Ø JDBC连接MySQL
Class.forName("org.gjt.mm.mysql.Driver");
cn=DriverManager.getConnection("jdbc:
mysql:
//DBServerIP:
3306/myDatabaseName",sUsr,sPwd);
Ø JDBC连接Oracle
Class.forName("oracle.jdbc.driver.OracleDriver");
cn=DriverManager.getConnection("jdbc:
oracle:
thin:
@MyDbComputerNameOrIP:
1521:
ORCL",sUsr,sPwd);
Ø JDBC连接DB2
Class.forName("C.DB2Driver");
Stringurl="jdbc:
db2:
//dburl:
port/DBname"
cn=DriverManager.getConnection(url,sUsr,sPwd);
Ø JDBC连接MicrosoftSQLServer
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
cn=DriverManager.getConnection("jdbc:
microsoft:
sqlserver:
//DBServerIP:
1433;databaseName=master",sUsr,sPwd);
Ø JDBC连接Sybase
Class.forName("com.sybase.jdbc2.jdbc.SybDriver");
cn=DriverManager.getConnection("jdbc:
sybase:
Tds:
DBServerIP:
2638",sUsr,sPwd);
Ø JDBC连接PostgreSQL
Class.forName("org.postgresql.Driver");
cn=DriverManager.getConnection("jdbc:
postgresql:
//DBServerIP/myDatabaseName",sUsr,sPwd);
Ø JDBC连接ODBC
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connectioncn=DriverManager.getConnection("jdbc:
odbc:
"+sDsn,sUsr,sPwd);
12.6 组合模式(Composite)
本节从以下几个方面来详细讲解组合模式:
Ø 组合模式的核心思想—树形结构。
Ø 何时使用组合模式。
Ø Java中的应用—AWT容器Container。
12.6.1 组合模式的核心思想—树形结构
组合模式有时候又叫做部分—整体模式,它使我们在处理树形结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
将对象组合成树形结构以表示“部分—整体”的层次结构。
组合模式使得用户对单个对象和组合对象的使用具有一致性。
如图12-23所示,TreeNode可以包含n个TreeNode节点对象,并可以通过add()和remove()来增加和删除这些对象,从而形成树,这就是组合模式的体现。
图12-23 组合模式树形结构
TreeNode.java类本身就是一个组合模式类,它使用一个集合对象children来组合它的所有孩子节点,并可以提供parent来返回其父亲节点。
其源代码如程序12-45所示。
程序12-45 树节点TreeNode.java
packageposite;
importjava.util.Enumeration;
importjava.util.Vector;
/**
*@authorliuzhongbing
*合成模式
*/
publicclassTreeNode{
privateStringname;//节点名称
privateTreeNodeparent;//父节点
privateVector
publicTreeNode(Stringname){
this.name=name;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicTreeNodegetParent(){
returnparent;
}
publicvoidsetParent(TreeNodeparent){
this.parent=parent;
}
//添加孩子节点
publicvoidadd(TreeNodenode){
children.add(node);
}
//删除孩子节点
publicvoidremove(TreeNodenode){
children.remove(node);
}
//取得孩子节点
publicEnumeration
returnchildren.elements();
}
}
使用该树节点我们可以构造一颗树,只需要从树根开始进行构造。
例如,我们要构建如下的一棵树:
A
/ | \
B C D
/ | |
E F G
需要先创建一个A树节点,然后分别创建B、C、D、E、F、G节点,并将E加入到B,F加入到C,G加入到D,B、C、D加入到A中。
其源代码如程序12-46所示。
程序12-46 树节点类实例TreeNode.java
packageposite;
publicclassTree{
TreeNoderoot=null;
publicTree(Stringname){
root=newTreeNode(name);
}
publicvoidtest(){
// A
// /|\
// BCD
// /||
//EFG
Treetree=newTree("A");
TreeNodenodeB=newTreeNode("B");
TreeNodenodeC=newTreeNode("C");
TreeNodenodeD=newTreeNode("D");
TreeNodenodeE=newTreeNode("E");
TreeNodenodeF=newTreeNode("F");
TreeNodenodeG=newTreeNode("G");
nodeB.add(nodeE);
nodeB.add(nodeF);
nodeC.add(nodeG);
tree.root.add(nodeB);
tree.root.add(nodeC);
tree.root.add(nodeD);
}
}
12.6.2 何时使用组合模式
组合模式也是一种对象的适配器模式,它将多个对象组合在一起进行操作;同时它又是一种桥接模式,它可以通过add()和remove()方法来添加和删除多个对象,即实现了桥的功能。
根据组合模式的特点,它最常用的就是在树形结构的表示中。
例如二叉树、多叉树等,通常用来表示有树形结构的数据集合。
12.6.3 Java中的应用—AWT容器Container
AWT提供了大量的组件和容器,包括窗体、菜单和各种输入组件。
AWT类全部在java.awt包中,Java图形用户界面的最基本组成部分是组件(Component),组件是一个可以以图形化的方式显示在屏幕上并能与用户进行交互的对象,例如一个按钮、一个标签等。
组件不能独立地显示出来,必须将组件放在一定的容器中才可以显示出来。
类java.awt.Component是许多组件类的父类,Component类中封装了组件通用的方法和属性,如图形的组件对象、大小、显示位置、前景色和背景色、边界、可见性等。
容器java.awt.Container是Component的子类,因此容器本身也是一个组件,它具有组件的所有性质,但是它的主要功能是容纳其他组件和容器。
一个容器可以容纳多个组件,并使它们成为一个整体。
容器可以简化图形化界面的设计,以整体结构来布置界面。
所有的容器都可以通过add()方法向容器中添加组件。
因此,这里的容器类就是组件类的组合,所有的子容器类型都可以拥有多个Component的子类型对象,如图12-24所示。
图12-24 AWT容器Container组合模式
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 模式 深入