观察者模式(Observer)
观察者模式也被称为发布订阅模式,在对象之间定义一个一对多的依赖,被依赖对象状态改变的时候,所有依赖的对象都会自动收到通知。下面我们通过一个例子来感受一下。
@AllArgsConstructor@Getterclass Message{String msg;}interface Publisher{void register(Subscriber subscriber);void remove(Subscriber subscriber);void publish(Message msg);}interface Subscriber{void subscribe(Message msg);}class AnyPublisher implements Publisher{private final Map<Integer,Subscriber> subMap=new HashMap<>();@Overridepublic void register(Subscriber subscriber) {subMap.putIfAbsent(subscriber.hashCode(),subscriber);}@Overridepublic void remove(Subscriber subscriber) {subMap.remove(subscriber.hashCode());}@Overridepublic void publish(Message msg) {subMap.forEach((k,v) -> {v.subscribe(msg);});}}@AllArgsConstructorclass EmailSubscriber implements Subscriber{private final String emailAddr;@Overridepublic void subscribe(Message msg) {System.out.println(emailAddr+": "+msg.getMsg());}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;EmailSubscriber that = (EmailSubscriber) o;return Objects.equals(emailAddr, that.emailAddr);}@Overridepublic int hashCode() {return Objects.hash(emailAddr);}}
我们再来看一下使用方法。
Publisher publisher=new AnyPublisher();publisher.register(new EmailSubscriber("LiLei"));publisher.register(new EmailSubscriber("HanMeiMei"));publisher.publish(new Message("Fake News"));
假如以后我们还想通过手机短信订阅消息,那么只需要创建一个TelSubscriber对象并将其注册到Publisher中即可,至于怎样才能将消息发送到用户那儿Publisher根本不关心,它只提供消息,Subscriber对消息发送方式拥有绝对的控制权,这样一来系统的可扩展性就得到了极大的提高。
模板模式(Template)
模板方法在一个方法中定义一个算法骨架,并将某些步骤推迟到子类实现。模板方法可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。例如,在JDK AbstractList类中,addAll()函数可以看作模板方法,add()方法是子类中需要重写的方法。这样一来,add()方法如何变化,都不需要重写addAll()方法,从而无论是ArrayList还是LinkedList都无需重写addAll()方法。
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>{public void add(int index, E element) {throw new UnsupportedOperationException();}public boolean addAll(int index, Collection<? extends E> c) {rangeCheckForAdd(index);boolean modified = false;for (E e : c) {add(index++, e);modified = true;}return modified;}}
策略模式(Strategy)
职责链模式(Chain)
状态模式
对于状态多,状态转移复杂的状态机而言,推荐使用查表法。而状态少,状态转移简单但是业务逻辑复杂的场景推荐使用状态机模式。
以如下的状态机为例。
enum State{SMALL,SUPER,FIRE,CAPE;}abstract class AbstractMario{State getName(){return State.SMALL;}void obtainMushRoom(){}void obtainCape(){}void obtainFireFlower(){}void meetMonster(){}}@AllArgsConstructorclass SmallMario extends AbstractMario{private final MarioStateMachine stateMachine;@Overridepublic State getName() {return State.SMALL;}@Overridepublic void obtainMushRoom() {stateMachine.setCurrentState(new SuperMario(stateMachine));stateMachine.setScore(stateMachine.getScore()+100);}@Overridepublic void obtainCape() {stateMachine.setCurrentState(new CapeMario(stateMachine));stateMachine.setScore(stateMachine.getScore()+200);}@Overridepublic void obtainFireFlower() {stateMachine.setCurrentState(new FireMario(stateMachine));stateMachine.setScore(stateMachine.getScore()+300);}}@AllArgsConstructorclass SuperMario extends AbstractMario{private final MarioStateMachine stateMachine;@Overridepublic State getName() {return State.SUPER;}@Overridepublic void obtainCape() {stateMachine.setCurrentState(new CapeMario(stateMachine));stateMachine.setScore(stateMachine.getScore()+200);}@Overridepublic void obtainFireFlower() {stateMachine.setCurrentState(new FireMario(stateMachine));stateMachine.setScore(stateMachine.getScore()+300);}@Overridepublic void meetMonster() {stateMachine.setCurrentState(new SmallMario(stateMachine));stateMachine.setScore(stateMachine.getScore()-100);}}@AllArgsConstructorclass FireMario extends AbstractMario{private final MarioStateMachine stateMachine;@Overridepublic State getName() {return State.FIRE;}@Overridepublic void meetMonster() {stateMachine.setCurrentState(new SmallMario(stateMachine));stateMachine.setScore(stateMachine.getScore()-300);}}@AllArgsConstructorclass CapeMario extends AbstractMario{private final MarioStateMachine stateMachine;@Overridepublic State getName() {return State.CAPE;}@Overridepublic void meetMonster() {stateMachine.setCurrentState(new SmallMario(stateMachine));stateMachine.setScore(stateMachine.getScore()-200);}}class MarioStateMachine{private int score;private AbstractMario currentState;public MarioStateMachine(){this.score=0;this.currentState=new SmallMario(this);}public void obtainMushRoom(){currentState.obtainMushRoom();}public void obtainCape(){currentState.obtainCape();}public void obtainFireFlower(){currentState.obtainFireFlower();}public void meetMonster(){currentState.meetMonster();}public int getScore() {return score;}public State getCurrentState() {return currentState.getName();}public void setScore(int score) {this.score = score;}public void setCurrentState(AbstractMario currentState) {this.currentState = currentState;}}
