9 Bridge模式——将类的功能层级结构与实现层次结构分离

9.1 Bridge模式

Bridge模式的作用是将两样东西连接起来,它们分别是类的功能层次类的实现层次。

类测层次结构的两个作用

  • 希望增加新功能是

假设现在有一个类Something。当我们想在Something中增加新功能时,会编写一个Something的子类(派生类),即SomethingGood类。这样就构成了一个小小的类层级结构。
image.png

这就是为了增加新功能而产生的层级结构。

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

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


  • 希望增加新的实现时

抽象类声明了一些抽象方法,定义了接口,然后子类负责去实现这些抽象方法。父类的任务是通过声明抽象方法定义接口。然后子类的任务是实现抽象方法。正是由于父类和子类的这种任务分担,我们才可以编写出具有高可替换性的类。
但是,这里的类层次结构并非用于增加功能,也就是说,这种层次结构并非用于方便增加新的方法。它的真正作用是帮助我们实现下面的任务分担。

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

这种层次结构被称为“类的实现层级结构
image.png


  • 类的层级结构的混杂与分离


9.2 示例

在桥的哪一侧 名字 说明
类的功能层次结构 Display 负责“显示”的类
类的功能层次结构 CountDisplay 增加了“只显示规定次数”,这一功能的类
类的实现层次结构 DisplayImpl 负责显示的类
类的实现层次结构 StringDisplayImpl “用字符串显示”的类

image.png

类的功能层级结构:Display

  1. public class Display {
  2. private DisplayImpl impl;
  3. public Display(DisplayImpl impl) {
  4. this.impl = impl;
  5. }
  6. public void open() {
  7. impl.rawOpen();
  8. }
  9. public void print() {
  10. impl.rawPrint();
  11. }
  12. public void close() {
  13. impl.rawClose();
  14. }
  15. public final void display() {
  16. open();
  17. print();
  18. close();
  19. }
  20. }


类的功能层次结构:CountDisplay类

  1. public class CountDisplay extends Display {
  2. public CountDisplay(DisplayImpl impl) {
  3. super(impl);
  4. }
  5. public void multiDisplay(int times) { // 循环显示times次
  6. open();
  7. for (int i = 0; i < times; i++) {
  8. print();
  9. }
  10. close();
  11. }
  12. }


类的实现层次结构:DisplayImpl类

  1. public abstract class DisplayImpl {
  2. public abstract void rawOpen();
  3. public abstract void rawPrint();
  4. public abstract void rawClose();
  5. }

9.3 Bridge模式中的角色

  • Abstraction(抽象化) 该角色位于“类的功能层级结构”的最上层。它使用Implementor角色的方法定义了基本的功能。该角色中保存了Implementor角色的实例。
  • RefinedAbstraction(改善后的抽象化):在Abstraction基础上增加了新功能的角色
  • Implementor(实现者):该角色位于“类的实现层次结构”,定义了用于实现Abstraction角色的接口。
  • ConcreteImplementor(具体的实现者):该角色负责实现Implementor角色中定义的接口。

image.png

10 Strategy模式——整体替换地算法

策略模式

10.2 示例程序

类和接口的一览表

名字 说明
Hand 表示猜拳游戏中的“手势”类
Strategy 表示猜拳游戏中的策略的类
WinningStrategy 表示“如果这局猜拳获胜,那么下一句也出一样的手势”这一策略
ProbStratrgy 表示“根据上一句的手势从概率上计算出下一句的手势从之前的猜拳结果计算出各种拳的概率”这一策略
Player 表示进行猜拳游戏的选手的类
Main 测试程序行为的类

image.png

Hand类

虽然Hand类会被其他类使用,但是它并非策略模式中的角色。

  1. public class Hand {
  2. public static final int HANDVALUE_GUU = 0; // 表示石头的值
  3. public static final int HANDVALUE_CHO = 1; // 表示剪刀的值
  4. public static final int HANDVALUE_PAA = 2; // 表示布的值
  5. public static final Hand[] hand = { // 表示猜拳中3种手势的实例
  6. new Hand(HANDVALUE_GUU),
  7. new Hand(HANDVALUE_CHO),
  8. new Hand(HANDVALUE_PAA),
  9. };
  10. private static final String[] name = { // 表示猜拳中手势所对应的字符串
  11. "石头", "剪刀", "布",
  12. };
  13. private int handvalue; // 表示猜拳中出的手势的值
  14. private Hand(int handvalue) {
  15. this.handvalue = handvalue;
  16. }
  17. public static Hand getHand(int handvalue) { // 根据手势的值获取其对应的实例
  18. return hand[handvalue];
  19. }
  20. public boolean isStrongerThan(Hand h) { // 如果this胜了h则返回true
  21. return fight(h) == 1;
  22. }
  23. public boolean isWeakerThan(Hand h) { // 如果this输给了h则返回true
  24. return fight(h) == -1;
  25. }
  26. private int fight(Hand h) { // 计分:平0, 胜1, 负-1
  27. if (this == h) {
  28. return 0;
  29. } else if ((this.handvalue + 1) % 3 == h.handvalue) {
  30. return 1;
  31. } else {
  32. return -1;
  33. }
  34. }
  35. public String toString() { // 转换为手势值所对应的字符串
  36. return name[handvalue];
  37. }
  38. }

Strategy接口

  1. public interface Strategy {
  2. Hand nextHand();
  3. void study(boolean win);
  4. }

WinningStrategy

  1. public class WinningStrategy implements Strategy {
  2. private Random random;
  3. private boolean won = false;
  4. private Hand prevHand;
  5. public WinningStrategy(int seed) {
  6. random = new Random(seed);
  7. }
  8. @Override
  9. public Hand nextHand() {
  10. if (!won) {
  11. prevHand = Hand.getHand(random.nextInt(3));
  12. }
  13. return prevHand;
  14. }
  15. @Override
  16. public void study(boolean win) {
  17. won = win;
  18. }
  19. }

10.3 Strategy模式中的角色

策略模式有以下几种角色

  • Strategy(策略) 负责实现策略所必需的接口。
  • ConcreteStrategy(具体的策略):负责实现具体的策略。
  • Context(上下文):保存了ConcreteStrategy角色的实例。

image.png