【笔记整理】图解设计模式 | 第9章 Bridge模式(将类的功能层次结构与实现层次结构分离)

【笔记整理】图解设计模式 | 导航


定义

  • 在“类的功能层次结构”和“类的实现层次结构”之间搭建桥梁。

类的层次结构的两个作用

希望增加新功能时

  • 父类具有基本功能
  • 在子类中增加新的功能

以上这种层次结构被称为“类的功能层次结构”

当要增加新的功能时,我们可以从各个层次的类中找出最符合自己需求的类,然后以它为父类编写子类,并在子类中增加新的功能。这就是“类的功能层次结构”。

希望增加新的实现时

  • 父类通过声明抽象方法来定义接口(API)
  • 子类通过实现具体方法来实现接口(API)

这种层次结构被称为“类的实现层次结构”。

当我们以其他方法实现AbstractClass时,例如要实现一个AnotherConcreteClass时,类的层次结构会稍微发生一些变化。

为了一种新的实现方式,我们继承了AbstractClass的子类,并实现了其中的抽象方法。这就是“类的实现层次结构”。

类的层次结构的混杂与分离

在编写子类时,需要先确认自己的意图:“我是要增加功能呢?还是要增加实现呢?”当类的层次结构只有一层时,功能层次结构与实现层次结构是混杂在一个层次结构中的。这样很容易使类的层次结构变得复杂,也难以透彻地理解类的层次结构。因为自己难以确定究竟应该在类的哪一个层次结构去增加子类。

因此需要将“类的功能层次结构”与“类的实现层次结构”分离为两个独立的类层次结构。还需要在它们之间搭建一座桥梁。


Bridge模式中的登场角色

  • Abstraction(抽象化)

       该角色位于“类的功能层次结构”的最上层。它使用Implementor角色的方法定义了基本的功能。该角色保存了Implementor角色的实例。

  • RefinedAbstraction(改善后的抽象化)

       在Abstraction角色基础上增加了新功能的角色。

  • Implementor(实现者)

       该角色位于“类的实现层次结构”的最上层。它定义了用于实现Abstraction角色的接口(API)的方法。

  • ConcreteImplementor(具体实现者)

       该角色负责实现在Implementor角色中定义的接口(API)。


Brideg模式的类图

左侧的两个类构成了“类的功能层次结构”,右侧两个类构成了“类的实现层次结构”。两个类的层次结构之间的桥梁是impl字段(采用委托方式)。


拓展思路的要点

  • 分开后更容易扩展

       将类的这两个层次结构分离开有利于独立地对它们进行扩展。

       当想要增加功能时,只需要在“类的功能层次结构”一侧增加类即可,不必对“类的实现层次结构”做任何修改。而且,增加后的功能可以被“所有的实现”使用

  • 继承是强关联,委托是弱关联

       虽然使用“继承”很容易扩展类,但是类之间也形成了一种强关联关系。

       如果想要很轻松地改变类之间的关系,使用继承就不合适了,因为每次改变类之间关系时都需要修改程序。这时,我们可以使用“委托”来代替“继承”关系。


相关的设计模式

       在Template Method模式中使用了“类的实现层次结构”。父类调用抽象方法,而子类实现抽象方法。

       为了能够根据需求设计出良好的ConcreteImplementor角色,有时我们会使用Abstract Factory模式。

       使用Bridge模式可以达到类的功能层次结构与类的实现层次结构分离的目的,并在此基础上使这些层次结构结合起来。

       而使用Adapter模式则可以结合那些功能上相似但是接口(API)不同的类。


代码

  • Abstraction(抽象化)
public class Display {

	private DisplayImpl impl;

	public Display(DisplayImpl impl) {
		this.impl = impl;
	}

	public void open() {
		impl.rawOpen();
	}

	public void print() {
		impl.rawPrint();
	}

	public void close() {
		impl.rawClose();
	}

	public final void display() {
		open();
		print();
		close();
	}
}
  • RefinedAbstraction(改善后的抽象化)
public class CountDisplay extends Display {

	public CountDisplay(DisplayImpl impl) {
		super(impl);
	}

	// 增加功能(功能层次结构)
	public void multiDisplay(int times) { // 循环显示times次
		open();
		for (int i = 0; i < times; i++) {
			print();
		}
		close();
	}
}
  • Implementor(实现者)
public abstract class DisplayImpl {

	public abstract void rawOpen();

	public abstract void rawPrint();

	public abstract void rawClose();
}
  • ConcreteImplementor(具体实现者)
public class StringDisplayImpl extends DisplayImpl {

	private String string;
	private int width;

	public StringDisplayImpl(String string) {
		this.string = string;
		this.width = string.getBytes().length;
	}

	@Override
	public void rawOpen() {
		printLine();
	}

	@Override
	public void rawPrint() {
		System.out.println("|" + string + "|");
	}

	@Override
	public void rawClose() {
		printLine();
	}

	private void printLine() {
		System.out.print("+");
		for (int i = 0; i < width; i++) {
			System.out.print("-");
		}
		System.out.println("+");
	}
}
  • Main类
public class Main {

	public static void main(String[] args) {
		Display d1 = new Display(new StringDisplayImpl("Hello, China."));
		Display d2 = new CountDisplay(new StringDisplayImpl("Hello, World."));
		CountDisplay d3 = new CountDisplay(new StringDisplayImpl("Hello, Universe."));
		d1.display();
		d2.display();
		d3.display();
		d3.multiDisplay(5);
	}

}

注:博客中的图片来自网上。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值