结构型模式——桥接模式

桥接模式的定义与特点

桥接(Bridge)模式的定义如下:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

桥接(Bridge)模式的优点是:

  • 由于抽象与实现分离,所以扩展能力强;
  • 其实现细节对客户透明。


缺点是:由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,这增加了系统的理解与设计难度。

桥接模式的结构与实现

可以将抽象化部分与实现化部分分开,取消二者的继承关系,改用组合关系。

1. 模式的结构

桥接(Bridge)模式包含以下主要角色。

  1. 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。
  2. 扩展抽象化(Refined    Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
  3. 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
  4. 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。


其结构图如图 1 所示。
 

桥接模式的结构图
图1 桥接模式的结构图

2. 模式的实现

桥接模式的代码如下:

 
  1. package bridge;
  2. public class BridgeTest
  3. {
  4. public static void main(String[] args)
  5. {
  6. Implementor imple=new ConcreteImplementorA();
  7. Abstraction abs=new RefinedAbstraction(imple);
  8. abs.Operation();
  9. }
  10. }
  11. //实现化角色
  12. interface Implementor
  13. {
  14. public void OperationImpl();
  15. }
  16. //具体实现化角色
  17. class ConcreteImplementorA implements Implementor
  18. {
  19. public void OperationImpl()
  20. {
  21. System.out.println("具体实现化(Concrete Implementor)角色被访问" );
  22. }
  23. }
  24. //抽象化角色
  25. abstract class Abstraction
  26. {
  27. protected Implementor imple;
  28. protected Abstraction(Implementor imple)
  29. {
  30. this.imple=imple;
  31. }
  32. public abstract void Operation();
  33. }
  34. //扩展抽象化角色
  35. class RefinedAbstraction extends Abstraction
  36. {
  37. protected RefinedAbstraction(Implementor imple)
  38. {
  39. super(imple);
  40. }
  41. public void Operation()
  42. {
  43. System.out.println("扩展抽象化(Refined Abstraction)角色被访问" );
  44. imple.OperationImpl();
  45. }
  46. }


程序的运行结果如下:

扩展抽象化(Refined Abstraction)角色被访问
具体实现化(Concrete Implementor)角色被访问

桥接模式的应用实例

【例1】用桥接(Bridge)模式模拟女士皮包的选购。

分析:女士皮包有很多种,可以按用途分、按皮质分、按品牌分、按颜色分、按大小分等,存在多个维度的变化,所以采用桥接模式来实现女士皮包的选购比较合适。

本实例按用途分可选钱包(Wallet)和挎包(HandBag),按颜色分可选黄色(Yellow)和红色(Red)。可以按两个维度定义为颜色类和包类。(点此下载本实例所要显示的包的图片)。

颜色类(Color)是一个维度,定义为实现化角色,它有两个具体实现化角色:黄色和红色,通过 getColor() 方法可以选择颜色;包类(Bag)是另一个维度,定义为抽象化角色,它有两个扩展抽象化角色:挎包和钱包,它包含了颜色类对象,通过 getName() 方法可以选择相关颜色的挎包和钱包。

客户类通过 ReadXML 类从 XML 配置文件中获取包信息(点此下载 XML 配置文件),并把选到的产品通过窗体显示出现,图 2 所示是其结构图。
 

女士皮包选购的结构图
图2 女士皮包选购的结构图


程序代码如下:

 
  1. package bridge;
  2. import java.awt.*;
  3. import javax.swing.*;
  4. public class BagManage
  5. {
  6. public static void main(String[] args)
  7. {
  8. Color color;
  9. Bag bag;
  10. color=(Color)ReadXML.getObject("color");
  11. bag=(Bag)ReadXML.getObject("bag");
  12. bag.setColor(color);
  13. String name=bag.getName();
  14. show(name);
  15. }
  16. public static void show(String name)
  17. {
  18. JFrame jf=new JFrame("桥接模式测试");
  19. Container contentPane=jf.getContentPane();
  20. JPanel p=new JPanel();
  21. JLabel l=new JLabel(new ImageIcon("src/bridge/"+name+".jpg"));
  22. p.setLayout(new GridLayout(1,1));
  23. p.setBorder(BorderFactory.createTitledBorder("女士皮包"));
  24. p.add(l);
  25. contentPane.add(p, BorderLayout.CENTER);
  26. jf.pack();
  27. jf.setVisible(true);
  28. jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  29. }
  30. }
  31. //实现化角色:颜色
  32. interface Color
  33. {
  34. String getColor();
  35. }
  36. //具体实现化角色:黄色
  37. class Yellow implements Color
  38. {
  39. public String getColor()
  40. {
  41. return "yellow";
  42. }
  43. }
  44. //具体实现化角色:红色
  45. class Red implements Color
  46. {
  47. public String getColor()
  48. {
  49. return "red";
  50. }
  51. }
  52. //抽象化角色:包
  53. abstract class Bag
  54. {
  55. protected Color color;
  56. public void setColor(Color color)
  57. {
  58. this.color=color;
  59. }
  60. public abstract String getName();
  61. }
  62. //扩展抽象化角色:挎包
  63. class HandBag extends Bag
  64. {
  65. public String getName()
  66. {
  67. return color.getColor()+"HandBag";
  68. }
  69. }
  70. //扩展抽象化角色:钱包
  71. class Wallet extends Bag
  72. {
  73. public String getName()
  74. {
  75. return color.getColor()+"Wallet";
  76. }
  77. }
 
  1. package bridge;
  2. import javax.xml.parsers.*;
  3. import org.w3c.dom.*;
  4. import java.io.*;
  5. class ReadXML
  6. {
  7. public static Object getObject(String args)
  8. {
  9. try
  10. {
  11. DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
  12. DocumentBuilder builder=dFactory.newDocumentBuilder();
  13. Document doc;
  14. doc=builder.parse(new File("src/bridge/config.xml"));
  15. NodeList nl=doc.getElementsByTagName("className");
  16. Node classNode=null;
  17. if(args.equals("color"))
  18. {
  19. classNode=nl.item(0).getFirstChild();
  20. }
  21. else if(args.equals("bag"))
  22. {
  23. classNode=nl.item(1).getFirstChild();
  24. }
  25. String cName="bridge."+classNode.getNodeValue();
  26. Class<?> c=Class.forName(cName);
  27. Object obj=c.newInstance();
  28. return obj;
  29. }
  30. catch(Exception e)
  31. {
  32. e.printStackTrace();
  33. return null;
  34. }
  35. }
  36. }


程序的运行结果如图 3 所示。
 

女士皮包选购的运行结果1
图3 女士皮包选购的运行结果1


如果将 XML 配置文件按如下修改:

 
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <config>
  3. <className>Red</className>
  4. <className>Wallet</className>
  5. </config>


则程序的运行结果如图 4 所示。
 

女士皮包选购的运行结果2
图4 女士皮包选购的运行结果2

桥接模式的应用场景

桥接模式通常适用于以下场景。

  1. 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
  2. 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
  3. 当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。

桥接模式模式的扩展

在软件开发中,有时桥接(Bridge)模式可与适配器模式联合使用。当桥接(Bridge)模式的实现化角色的接口与现有类的接口不一致时,可以在二者中间定义一个适配器将二者连接起来,其具体结构图如图 5 所示。
 

桥接模式与适配器模式联用的结构图
图5 桥接模式与适配器模式联用的结构图

 

摘至:http://m.biancheng.net/view/1364.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
桥接模式是一种结构型设计模式,它将抽象和实现分离,使它们可以独立地变化。桥接模式的核心思想是将一个大类或一组类分解成抽象和实现两个独立的维度,使它们可以独立地变化和扩展,同时通过桥接来将它们连接起来。 在C++中,桥接模式通常通过虚函数实现。抽象部分通过基类定义接口,而实现部分通过派生类实现具体的功能。通过将抽象部分的指针作为参数传递给实现部分的函数,就可以实现两个部分的连接。 下面是一个简单的桥接模式的C++示例: ```c++ class Implementor { public: virtual void operation() = 0; virtual ~Implementor() {} }; class ConcreteImplementorA : public Implementor { public: void operation() override { // 具体的实现A } }; class ConcreteImplementorB : public Implementor { public: void operation() override { // 具体的实现B } }; class Abstraction { public: Abstraction(Implementor* implementor) : m_implementor(implementor) {} virtual void operation() = 0; virtual ~Abstraction() {} protected: Implementor* m_implementor; }; class RefinedAbstraction : public Abstraction { public: RefinedAbstraction(Implementor* implementor) : Abstraction(implementor) {} void operation() override { m_implementor->operation(); // 其他操作 } }; int main() { Implementor* implementorA = new ConcreteImplementorA(); Implementor* implementorB = new ConcreteImplementorB(); Abstraction* abstractionA = new RefinedAbstraction(implementorA); Abstraction* abstractionB = new RefinedAbstraction(implementorB); abstractionA->operation(); abstractionB->operation(); delete abstractionA; delete abstractionB; delete implementorA; delete implementorB; return 0; } ``` 在上面的示例中,Implementor是实现部分的抽象基类,ConcreteImplementorA和ConcreteImplementorB是具体的实现类。Abstraction是抽象部分的基类,RefinedAbstraction是抽象部分的具体实现类。在main函数中,我们创建了不同的Implementor和Abstraction对象,并通过它们来完成不同的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值