12责任链模式
定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
package com.simple.gof.responsibility;
/**
* 责任链处理器
*
* @author chaozai
* @date 2018年8月21日
*
*/
public abstract class Handler {
Handler nextHandler;
public void setNext(Handler nextHandler) {
this.nextHandler = nextHandler;
}
/**
* 责任链传递任务核心代码,禁止子类修改该方法
*
* @param request
*/
public final void handleRequest(Object request) {
this.doJob();
if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
/**
* 子类实现具体处理逻辑
*/
protected abstract void doJob();
}
总结:职责链将请求的发送者和请求的处理者一定程度解耦了,任务交由责任链按需分配,处理者可以分工更加细致,责任单一化;同一事件在运行时决定被哪个处理器处理,可以同时被多个处理
使用场景:拦截器;过滤器;数据清洗,规则引擎
13命令模式
定义:将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。
命令对象
package com.simple.gof.command;
/**
* 命令对象:接收者和调用者的纽带
*
* @author chaozai
* @date 2018年8月22日
*
*/
public class Command {
/**
* 可以是包含多个责任链的执行者
*/
Receiver receiver;
public Command(Receiver receiver) {
this.receiver = receiver;
}
/**
* 可以是一系列模板操作
*/
public void execute() {
receiver.executeCommand();
}
}
命令调用者
package com.simple.gof.command;
/**
* 命令的调用者
*
* @author chaozai
* @date 2018年8月22日
*
*/
public class Invoker {
/**
* 可以是一个命令集合,能够撤销,重做,清理等
*/
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void action() {
this.command.execute();
}
}
总结:可以选择和责任链,模板等组合使用;如果把调用者看成客户端,命令对象相当于是执行者的门面,但门面出发点是解决执行者的复杂调用,命令模式是为了将调用者和执行者解耦,便于对命令执行过程进行扩展。
使用场景:GUI;操作系统命令调用;需要对行为进行记录、撤销或重做、事务等处理
14解释器模式
定义:给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
package com.simple.gof.interpreter;
/**
* 解释器
* @author chaozai
* @date 2018年8月22日
*
*/
public class Interpreter {
private String rule;
/**
*
* @param rule 解释规则
*/
public Interpreter(String rule) {
this.rule = rule;
}
/**
* 解释方法
* @param data 被解释内容
* @return
*/
public boolean interpret(String data){
if(data.contains(rule)){
return true;
}
return false;
}
}
使用场景:正则匹配;规则引擎;将字符串解析成对象,比如各种框架中的URL
15迭代器模式
定义:它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。
贴上Java8迭代器接口拷贝代码,使用迭代器,实现该接口即可。
package com.simple.gof.iterator;
import java.util.Objects;
import java.util.function.Consumer;
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
使用场景:异构集合统一遍历方式
16中介者模式
定义:用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
package com.simple.gof.mediator;
/**
* 中介者
* @author chaozai
* @date 2018年8月22日
*
*/
public class Mediator {
Object a;
Object b;
public Object getA() {
return a;
}
public void setA(Object a) {
this.a = a;
}
public Object getB() {
return b;
}
public void setB(Object b) {
this.b = b;
}
/**
* A与B交互方法
*/
void doSomethingWithAB(){}
}
使用场景:在类图中出现了蜘蛛网状结构,即每个类间联系复杂;任务调度;MVC-Controller层
17备忘录模式
定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
package com.simple.gof.memento;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
/**
* 备忘录工具类
* @author chaozai
* @date 2018年8月22日
*
*/
public class MementoUtil {
/**
* 发起备忘对象的所有属性及数值放入到Hashmap中
* @param originator 发起对象
* @return
*/
public static HashMap<String, Object> backupProp(Object originator) {
HashMap<String, Object> result = new HashMap<String, Object>();
try {
// 获得Bean描述
BeanInfo beanInfo = Introspector.getBeanInfo(originator.getClass());
// 获得属性描述
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
// 遍历所有属性
for (PropertyDescriptor des : descriptors) {
// 属性名称
String fieldName = des.getName();
// 读取属性的方法
Method getter = des.getReadMethod();
// 读取属性值
Object fieldValue = getter.invoke(originator, new Object[] {});
if (!fieldName.equalsIgnoreCase("class")) {
result.put(fieldName, fieldValue);
}
}
} catch (Exception e) {
// 异常处理
}
return result;
}
/**
*
* @param originator 待恢复的发起对象
* @param memento 备忘对象
*/
public static void restoreProp(Object originator, HashMap<String, Object> memento) {
try {
// 获得Bean描述
BeanInfo beanInfo = Introspector.getBeanInfo(originator.getClass());
// 获得属性描述
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
// 遍历所有属性
for (PropertyDescriptor des : descriptors) {
// 属性名称
String fieldName = des.getName();
// 如果有这个属性
if (memento.containsKey(fieldName)) {
// 写属性的方法
Method setter = des.getWriteMethod();
setter.invoke(originator, new Object[] { memento.get(fieldName) });
}
}
} catch (Exception e) {
// 异常处理
System.out.println("shit");
e.printStackTrace();
}
}
}
总结:发起人、备忘录、管理员(管理备忘历史集合)三者间的组合控制,可以依据实际应用场景来实现
使用场景:数据事务回滚;存档需求
18观察者模式
定义:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
java自带被观察主题父类
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;
public Observable() {
obs = new Vector<>();
}
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
主题类
package com.simple.gof.observer;
import java.util.Observable;
/**
* 被观察主题
*
* @author chaozai
* @date 2018年8月22日
*
*/
public class Subject extends Observable {
private Object data = null;
public Object getData() {
return data;
}
/**
* 更新数据
*
* @param data
*/
public void setData(Object data) {
this.data = data;
setChanged();
notifyObservers();
}
}
观察者类
package com.simple.gof.observer;
import java.util.Observable;
import java.util.Observer;
/**
* 观察者
* @author chaozai
* @date 2018年8月22日
*
*/
public class RealObserver implements Observer {
Observable observable;
Object data;
public RealObserver(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable observable, Object arg) {
if (observable instanceof Subject) {
Subject subject = (Subject) observable;
data = subject.getData();
}
}
}
使用场景:事件触发;跨系统消息交换
19状态模式
定义:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。将行为处理绑定到状态对象上。
状态
package com.simple.gof.state;
/**
* 状态接口
* @author chaozai
* @date 2018年8月22日
*
*/
public interface State {
void doSomething();
}
环境
package com.simple.gof.state;
/**
* 运行环境
* @author chaozai
* @date 2018年8月22日
*
*/
public class Context {
State state;
public void start() {
state = new StartState();
}
public void end(){
state = new EndState();
}
/**
* 由当前状态决定如何执行方法
*/
public void doSomething(){
state.doSomething();
}
}
使用场景:行为随状态改变而改变;替代重复条件判断;权限设计
20策略模式
定义:定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。
抽象策略
package com.simple.gof.strategy;
/**
* 抽象策略
* @author chaozai
* @date 2018年8月22日
*
*/
public abstract class Strategy {
abstract void doSomething();
}
策略使用上下文
package com.simple.gof.state;
/**
* 运行环境
* @author chaozai
* @date 2018年8月22日
*
*/
public class Context {
State state;
public void start() {
state = new StartState();
}
public void end(){
state = new EndState();
}
/**
* 由当前状态决定如何执行方法
*/
public void doSomething(){
state.doSomething();
}
}
使用场景:算法运行时调整;
21模板方法模式
定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
package com.simple.gof.template;
/**
* 模板抽象类
* @author chaozai
* @date 2018年8月22日
*
*/
public abstract class Template {
abstract void start();
abstract void end();
abstract void doSomething();
/**
* 模板方法不可覆盖
*/
public final void execute(){
start();
doSomething();
end();
}
}
使用场景:多个子类共有的方法,且逻辑相同;复杂算法,提取核心相同算法
22访问者模式
定义:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
package com.simple.gof.visitor;
/**
* 被访问者
* @author chaozai
* @date 2018年8月22日
*
*/
public class RealElement implements Element{
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
使用场景:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,可以将这些操作封装到访问者当中
总结
- 责任链:客户端与执行者适当解耦,处理者独立分工(单一职责)
- 命令:客户端与执行者完全解耦,命令是执行者和附加功能的门面,命令管理执行过程,执行者关注任务执行(单一职责)
- 解释器+备忘录:对象与其他格式数据的快捷转换
- 迭代器:相当于集合为它做适配,它又是遍历数据的(统一)门面
- 中介:复杂对象关系的简化(但可能会违背单一职责)
- 观察者:React模式,响应式编程
- 状态+策略:自动适应变化
- 模板:流程与实现解耦,模板定义不变流程,子类实现变化功能
- 访问者:局部变量临时访问,没必要让他成为成员变量,无需持久使用它
样例源码地址:https://github.com/qqchaozai/gof.git
爱家人,爱生活,爱设计,爱编程,拥抱精彩人生!