观察者模式(Observer)

观察者模式也被称为发布订阅模式,在对象之间定义一个一对多的依赖,被依赖对象状态改变的时候,所有依赖的对象都会自动收到通知。下面我们通过一个例子来感受一下。

  1. @AllArgsConstructor
  2. @Getter
  3. class Message{
  4. String msg;
  5. }
  6. interface Publisher{
  7. void register(Subscriber subscriber);
  8. void remove(Subscriber subscriber);
  9. void publish(Message msg);
  10. }
  11. interface Subscriber{
  12. void subscribe(Message msg);
  13. }
  14. class AnyPublisher implements Publisher{
  15. private final Map<Integer,Subscriber> subMap=new HashMap<>();
  16. @Override
  17. public void register(Subscriber subscriber) {
  18. subMap.putIfAbsent(subscriber.hashCode(),subscriber);
  19. }
  20. @Override
  21. public void remove(Subscriber subscriber) {
  22. subMap.remove(subscriber.hashCode());
  23. }
  24. @Override
  25. public void publish(Message msg) {
  26. subMap.forEach((k,v) -> {
  27. v.subscribe(msg);
  28. });
  29. }
  30. }
  31. @AllArgsConstructor
  32. class EmailSubscriber implements Subscriber{
  33. private final String emailAddr;
  34. @Override
  35. public void subscribe(Message msg) {
  36. System.out.println(emailAddr+": "+msg.getMsg());
  37. }
  38. @Override
  39. public boolean equals(Object o) {
  40. if (this == o) return true;
  41. if (o == null || getClass() != o.getClass()) return false;
  42. EmailSubscriber that = (EmailSubscriber) o;
  43. return Objects.equals(emailAddr, that.emailAddr);
  44. }
  45. @Override
  46. public int hashCode() {
  47. return Objects.hash(emailAddr);
  48. }
  49. }

我们再来看一下使用方法。

  1. Publisher publisher=new AnyPublisher();
  2. publisher.register(new EmailSubscriber("LiLei"));
  3. publisher.register(new EmailSubscriber("HanMeiMei"));
  4. publisher.publish(new Message("Fake News"));

假如以后我们还想通过手机短信订阅消息,那么只需要创建一个TelSubscriber对象并将其注册到Publisher中即可,至于怎样才能将消息发送到用户那儿Publisher根本不关心,它只提供消息,Subscriber对消息发送方式拥有绝对的控制权,这样一来系统的可扩展性就得到了极大的提高。

模板模式(Template)

模板方法在一个方法中定义一个算法骨架,并将某些步骤推迟到子类实现。模板方法可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。例如,在JDK AbstractList类中,addAll()函数可以看作模板方法,add()方法是子类中需要重写的方法。这样一来,add()方法如何变化,都不需要重写addAll()方法,从而无论是ArrayList还是LinkedList都无需重写addAll()方法。

  1. public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>{
  2. public void add(int index, E element) {
  3. throw new UnsupportedOperationException();
  4. }
  5. public boolean addAll(int index, Collection<? extends E> c) {
  6. rangeCheckForAdd(index);
  7. boolean modified = false;
  8. for (E e : c) {
  9. add(index++, e);
  10. modified = true;
  11. }
  12. return modified;
  13. }
  14. }

策略模式(Strategy)

待补充

职责链模式(Chain)

待补充

状态模式

对于状态多,状态转移复杂的状态机而言,推荐使用查表法。而状态少,状态转移简单但是业务逻辑复杂的场景推荐使用状态机模式。
以如下的状态机为例。
image.png

  1. enum State{
  2. SMALL,
  3. SUPER,
  4. FIRE,
  5. CAPE;
  6. }
  7. abstract class AbstractMario{
  8. State getName(){
  9. return State.SMALL;
  10. }
  11. void obtainMushRoom(){}
  12. void obtainCape(){}
  13. void obtainFireFlower(){}
  14. void meetMonster(){}
  15. }
  16. @AllArgsConstructor
  17. class SmallMario extends AbstractMario{
  18. private final MarioStateMachine stateMachine;
  19. @Override
  20. public State getName() {
  21. return State.SMALL;
  22. }
  23. @Override
  24. public void obtainMushRoom() {
  25. stateMachine.setCurrentState(new SuperMario(stateMachine));
  26. stateMachine.setScore(stateMachine.getScore()+100);
  27. }
  28. @Override
  29. public void obtainCape() {
  30. stateMachine.setCurrentState(new CapeMario(stateMachine));
  31. stateMachine.setScore(stateMachine.getScore()+200);
  32. }
  33. @Override
  34. public void obtainFireFlower() {
  35. stateMachine.setCurrentState(new FireMario(stateMachine));
  36. stateMachine.setScore(stateMachine.getScore()+300);
  37. }
  38. }
  39. @AllArgsConstructor
  40. class SuperMario extends AbstractMario{
  41. private final MarioStateMachine stateMachine;
  42. @Override
  43. public State getName() {
  44. return State.SUPER;
  45. }
  46. @Override
  47. public void obtainCape() {
  48. stateMachine.setCurrentState(new CapeMario(stateMachine));
  49. stateMachine.setScore(stateMachine.getScore()+200);
  50. }
  51. @Override
  52. public void obtainFireFlower() {
  53. stateMachine.setCurrentState(new FireMario(stateMachine));
  54. stateMachine.setScore(stateMachine.getScore()+300);
  55. }
  56. @Override
  57. public void meetMonster() {
  58. stateMachine.setCurrentState(new SmallMario(stateMachine));
  59. stateMachine.setScore(stateMachine.getScore()-100);
  60. }
  61. }
  62. @AllArgsConstructor
  63. class FireMario extends AbstractMario{
  64. private final MarioStateMachine stateMachine;
  65. @Override
  66. public State getName() {
  67. return State.FIRE;
  68. }
  69. @Override
  70. public void meetMonster() {
  71. stateMachine.setCurrentState(new SmallMario(stateMachine));
  72. stateMachine.setScore(stateMachine.getScore()-300);
  73. }
  74. }
  75. @AllArgsConstructor
  76. class CapeMario extends AbstractMario{
  77. private final MarioStateMachine stateMachine;
  78. @Override
  79. public State getName() {
  80. return State.CAPE;
  81. }
  82. @Override
  83. public void meetMonster() {
  84. stateMachine.setCurrentState(new SmallMario(stateMachine));
  85. stateMachine.setScore(stateMachine.getScore()-200);
  86. }
  87. }
  88. class MarioStateMachine{
  89. private int score;
  90. private AbstractMario currentState;
  91. public MarioStateMachine(){
  92. this.score=0;
  93. this.currentState=new SmallMario(this);
  94. }
  95. public void obtainMushRoom(){
  96. currentState.obtainMushRoom();
  97. }
  98. public void obtainCape(){
  99. currentState.obtainCape();
  100. }
  101. public void obtainFireFlower(){
  102. currentState.obtainFireFlower();
  103. }
  104. public void meetMonster(){
  105. currentState.meetMonster();
  106. }
  107. public int getScore() {
  108. return score;
  109. }
  110. public State getCurrentState() {
  111. return currentState.getName();
  112. }
  113. public void setScore(int score) {
  114. this.score = score;
  115. }
  116. public void setCurrentState(AbstractMario currentState) {
  117. this.currentState = currentState;
  118. }
  119. }