十八.备忘录模式(Memento Pattern)
简单点说,就是存档,保存一个对象在某个时刻的状态或部分状态,在未来某个时段需要时,将其还原到原来记录状态的模式
代码示例:
Java代码
/* 备忘录角色 —— 存档类*/
public class Memento {
private int hp;
private int mp;
private int money;
public Memento(int hp, int mp, int money) {
this.hp = hp;
this.mp = mp;
this.money = money;
}
/*getter和setter方法*/
}
/* 发起人角色 —— 角色类,属性定义,定义保存与恢复自身状态的方法 */
public class Character {
private int hp;
private int mp;
private int money;
public Character(int hp, int mp, int money) {
this.hp = hp;
this.mp = mp;
this.money = money;
}
/*getter和setter方法*/
public void showMsg() {
System.out.println("当前状态:| HP:" + hp + " | MP:" + mp + " | 金钱:" + money + "\n");
}
//创建一个备忘录,保存当前自身状态
public Memento save() { return new Memento(hp, mp, money); }
//传入一个备忘录对象,恢复内部状态
public void restore(Memento memento) {
this.hp = memento.getHp();
this.mp = memento.getMp();
this.money = memento.getMoney();
}
}
/* 备忘录管理者角色 —— 只负责备忘录对象的传递! 多个存档的话可用集合存,根据索引取*/
public class Caretaker {
private Memento memento;
public Memento getMemento() { return memento; }
public void setMemento(Memento memento) { this.memento = memento; }
}
/* 客户端调用 */
public class Client {
public static void main(String[] args) {
Caretaker caretaker= new Caretaker();
Character character = new Character(2000,1000,500);
//存档
System.out.println("=== 存档中... ===");
character.showMsg();
caretaker.setMemento(character.save());
System.out.println("=== 单挑Boss,不敌,金钱扣除一半... ===");
character.setHp(0);
character.setHp(0);
character.setHp(250);
character.showMsg();
//读档
System.out.println("=== 读取存档中... ===");
character.restore(caretaker.getMemento());
character.showMsg();
}
}
十九.中介者模式(Mediator Pattern)
用一个中介对象来封装一系列的对象交互,使得各对象不需要显式的相互引用, 从而使其耦合松散,而且可以独立的改变他们之间的交互。
中介者持有所有同事引用,然后在里面做一些逻辑操作,然后每个同事类持有中介者引用,依次完成交互。
这里的话需要与前面的外观模式,代理模式进行区分!
外观模式:结构型,对子系统提供统一的接口,单向,所有请求都委托子系统完成,树型
代理模式:结构型,引用代理对象的方式来访问目标对象,单向
中介者模式:行为型,用一个中介对象来封装一系列同事对象的交互行为,双向,一对多星型
UML类图
代码示例:
Java代码
/* 抽象中介类,有连接同事进行交互的方法*/
public abstract class Mediator {
abstract void contact(People people, String msg);
}
/* 抽象同事类,相关属性,还有一个中介类的引用,因为所有同事都知道中介*/
public abstract class People {
protected String name;
protected Mediator mediator; //每个人都知道中介
public People(String name, Mediator mediator) {
this.name = name;
this.mediator = mediator;
}
}
/* 具体同事类,这里是房东和房客*/
public class Landlord extends People {
public Landlord(String name, Mediator mediator) { super(name, mediator); }
public void contact(String msg) { mediator.contact(this, msg); }
public void getMessage(String msg) { System.out.println("【房东】" + name + ":" + msg); }
}
public class Tenant extends People {
public Tenant(String name, Mediator mediator) { super(name, mediator); }
public void contact(String msg) { mediator.contact(this, msg); }
public void getMessage(String msg) { System.out.println("【房客】" + name + ":" + msg); }
}
/* 具体中介类,中介者知道所有的同事,实现交互方法时对调用者进行判断
实现对应的逻辑,比如这里的信息显示*/
public class HouseMediator extends Mediator {
//中介者知道所有同事
private Landlord landlord;
private Tenant tenant;
public Landlord getLandlord() { return landlord; }
public void setLandlord(Landlord landlord) { this.landlord = landlord; }
public Tenant getTenant() { return tenant; }
public void setTenant(Tenant tenant) { this.tenant = tenant; }
@Override void contact(People people, String msg) {
if(people == tenant) tenant.getMessage(msg);
else landlord.getMessage(msg);
}
}
/* 客户端调用 */
public class Client {
public static void main(String[] args) {
//实例化中介者
HouseMediator mediator = new HouseMediator();
//实例化同事对象,传入中介者实例
Landlord landlord = new Landlord("包租婆",mediator);
Tenant tenant = new Tenant("小猪",mediator);
//为中介者传入同事实例
mediator.setLandlord(landlord);
mediator.setTenant(tenant);
//调用
landlord.contact("单间500一个月,有兴趣吗?");
tenant.contact("热水器,空调,网线有吗?");
landlord.contact("都有。");
tenant.contact("好吧,我租了。");
}
}
输出结果:
二十.解释器模式(Interpreter Pattern)
用得比较少的一种模式,定义也比较枯涩难懂,实在不理解可以先看代码:
给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器,客户端可以使用这个解释器来解释这个语言中的句子。
个人理解:
定义了一套简单语法,每个终结符都有一个对应的值存起来了,然后当你输了一串终结符,最后解释能得出一个正确结果。
代码示例:能够解释加减法的解释器
Java代码
/* 抽象表达式 */
public abstract class Expression {
public abstract int interpret(Context context);
@Override public abstract String toString();
}
/* 非终结符表达式 —— 加法和减法 */
public class PlusExpression extends Expression{
private Expression leftExpression;
private Expression rightExpression;
public PlusExpression(Expression leftExpression, Expression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
@Override public int interpret(Context context) {
return leftExpression.interpret(context) + rightExpression.interpret(context);
}
@Override public String toString() {
return leftExpression.toString() + " + " + rightExpression.toString();
}
}
public class MinusExpression extends Expression{ /* 和减法类似 */ }
/* 终结符表达式 —— 常量与变量*/
public class ConstantExpression extends Expression {
private int value;
public ConstantExpression(int value) { this.value = value; }
@Override public int interpret(Context context) { return value; }
@Override public String toString() { return Integer.toString(value); }
}
public class VariableExpression extends Expression {
private String name;
public VariableExpression(String name) { this.name = name; }
@Override public int interpret(Context context) { return context.lookup(this); }
@Override public String toString() { return name; }
}
/* 上下文环境 —— 用Map存放各个终结符对应的具体值*/
public class Context {
private Map
public void addExpression(Expression expression, int value) { map.put(expression, value); }
public int lookup(Expression expression) { return map.get(expression); }
}
/* 客户端调用 */
public class Client {
public static void main(String[] args) {
Context context = new Context();
VariableExpression a = new VariableExpression("a");
VariableExpression b = new VariableExpression("b");
ConstantExpression c = new ConstantExpression(6);
context.addExpression(a, 2);
context.addExpression(b, 3);
Expression expression = new PlusExpression(new PlusExpression(a,b),new MinusExpression(a,c));
System.out.println(expression.toString() + " = " + expression.interpret(context));
}
}
输出结果:
二十一.访问者模式(Visitor Pattern)
核心:数据结构不变,操作可变,结构与操作解耦的一种模式。
定义:封装一些作用域某种数据结构中的个元素的操作,在不改变这个
数据结构的前提下,定义作用于这些元素的新的操作。
代码示例:
Java代码
/* 元素角色 —— 游戏机接口,有一个传入访问者实例的方法 */
public interface Machine {
public void accept(Player player);
}
/* 具体元素 —— 投篮机,跳舞机和开车 */
public class Shooting implements Machine {
@Override public void accept(Player player) { player.visit(this); }
public String feature() { return "投篮机"; }
}
public class Dancing implements Machine { /*...*/ }
public class Driving implements Machine { /*...*/ }
/* 抽象访问者 —— 定义元素对应的访问方法,传入相应实例*/
public interface Player {
public void visit(Shooting machine);
public void visit(Dancing machine);
public void visit(Driving machine);
}
/* 具体访问者 —— 男女性玩家 */
public class MalePlayer implements Player{
@Override public void visit(Shooting machine) {
System.out.println("男性玩家玩:" + machine.feature());
}
@Override public void visit(Dancing machine) {
System.out.println("男性玩家玩:" + machine.feature());
}
@Override public void visit(Driving machine) {
System.out.println("男性玩家玩:" + machine.feature());
}
}
public class FemalePlayer implements Player{ /*...*/ }
/* 对象结构 —— 管理元素集合,并且可迭代访问者访问 */
public class GameRoom {
private List
public void add(Machine machine) { machines.add(machine); }
public void action(Player player) {
for (Machine machine: machines) { machine.accept(player); }
}
}
/* 客户端调用 */
public class Client {
public static void main(String[] args) {
GameRoom room = new GameRoom();
room.add(new Shooting());
room.add(new Dancing());
room.add(new Driving());
Player player1 = new MalePlayer();
Player player2 = new FemalePlayer();
room.action(player1);
room.action(player2);
}
}
输出结果:
二十二.责任链模式(Chain of Responsibility Pattern)
使多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。(典型代表:Android里的事件传递机制)
代码示例:
Java代码
/* 抽象处理者 */
public abstract class Handler {
private Handler nextHandler; /* 下家处理者 */
public Handler getNextHandler() { return nextHandler; }
public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; }
public abstract void handlerRequest(String str, int money); /* 请求 */
}
/* 具体处理者 —— 哥哥,爸爸,妈妈,依次传递*/
public class Brother extends Handler {
@Override public void handlerRequest(String str, int money) {
if(money <= 100) {
System.out.println("哥哥:100块,哥哥还是有的,给你~");
} else {
if(getNextHandler() != null) {
System.out.println("哥哥:大于100块,哥哥木有那么多钱,找粑粑去~");
getNextHandler().handlerRequest(str, money);
} else {
System.out.println("哥哥:大于100块,哥哥木有那么多钱,粑粑不在家~");
}
}
}
}
public class Father extends Handler {
@Override public void handlerRequest(String str, int money) {
if(money <= 500) {
System.out.println("粑粑:500块,粑粑还是有的,给你~");
} else {
if(getNextHandler() != null) {
System.out.println("粑粑:大于500块,粑粑木有那么多钱,找麻麻去~");
getNextHandler().handlerRequest(str, money);
} else {
System.out.println("粑粑:大于500块,粑粑木有那么多钱,麻麻不在家~");
}
}
}
}
public class Mother extends Handler {
@Override public void handlerRequest(String str, int money) {
if(money <= 1000) {
System.out.println("麻麻:1000块,麻麻还是有的,给你~");
} else {
System.out.println("麻麻:你拿那么多钱干嘛?");
}
}
}
/* 客户端调用 */
public class Client {
public static void main(String[] args) {
Brother brother = new Brother();
Father father = new Father();
Mother mother = new Mother();
//指定下家
brother.setNextHandler(father);
father.setNextHandler(mother);
brother.handlerRequest("要钱",1200);
}
}
输出结果:
另外责任链模式还分纯与不纯
纯责任链,要么承担全部责任,要么责任推个下家,不允许在某处承担了部分或者全部责任,然后又把责任推给下家。
不纯责任链,责任在某处部分或全部被处理后,还向下传递。
二十三.状态模式(State Pattern)
定义:当一个对象的内在状态发生改变时允许改变其行为,这个对象看起来像是改变了它的类。
套路:
抽象出状态State,然后实现该接口,然后具体化不同状态,做不同的操作,然后写一个Context,里面存储一个State的实例,然后定义一个可以修改State实例的方法,并在里面去调用实例的行为方法。
示例代码:
Java代码
/* 抽象状态 */
public interface State {
public void doSomeThing();
}
/* 具体状态 */
public class MorningState implements State {
@Override public void doSomeThing() { System.out.println("早上赖床!"); }
}
public class AfternoonState implements State {
@Override public void doSomeThing() { System.out.println("下午学习!"); }
}
public class EveningState implements State {
@Override public void doSomeThing() { System.out.println("晚上打球!"); }
}
/* 上下文环境 */
public class Context {
public void setState(State state) {
System.out.println("状态改变");
state.doSomeThing();
}
}
/* 客户端调用 */
public class Client {
public static void main(String[] args) {
MorningState morningState = new MorningState();
AfternoonState afternoonState = new AfternoonState();
EveningState eveningState = new EveningState();
Context context = new Context();
context.setState(morningState);
context.setState(afternoonState);
context.setState(eveningState);
}
}
输出结果:
二十四.模板方法模式(Template Method Pattern)
定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可冲定义该算法的某些特定步骤。(定义比较抽象,举之前工厂模式做奶茶的例子帮助理解下)
奶茶的制作步骤:加奶,加茶,加料,打包
在这几个步骤中,加奶,加茶,加料这几步是固定,而打包的话则是不固定的,有些用户喜欢找个小桌子喝喝奶茶吹吹水,有些喜欢带回家,存在可变性。
对于这种可变的步骤,可以使用一个叫做钩子的东西,其实就是一种被声明在抽象类的方法,可以为空或者默认的实现。钩子的存在可以让子类有能力对算法的不同点进行挂钩,是否需要挂钩由子类决定。比如例子通过一个标记确定是否需要打包,子类中可以定义一个方法来调用这个方法。
代码示例:
Java代码
/* 抽象模板 */
public abstract class Tea {
protected void 加奶() { System.out.println("加入三花淡奶"); }
protected abstract void 加茶();
protected abstract void 加料();
protected void 打包() { System.out.println("用打包机打包"); }
protected boolean 是否打包() { return true; } //钩子方法
public final void make() {
System.out.println("=== 开始制作 ===");
加奶();
加茶();
加料();
if(是否打包()) { 打包(); }
System.out.println("=== 制作完毕 ===");
}
}
/* 具体模板 */
public class RedTeaMilkTea extends Tea {
@Override protected void 加茶() { System.out.println("加入红茶"); }
@Override protected void 加料() { System.out.println("加入珍珠"); }
}
public class GreenTeaMilkTea extends Tea {
private boolean isPack = true;
public GreenTeaMilkTea(boolean isPack) { this.isPack = isPack; }
@Override protected void 加茶() { System.out.println("加入绿茶"); }
@Override protected void 加料() { System.out.println("加入椰果"); }
@Override protected boolean 是否打包() { return isPack; }
}
/* 客户端调用 */
public class Client {
public static void main(String[] args) {
Tea tea1 = new RedTeaMilkTea();
Tea tea2 = new GreenTeaMilkTea(false);
tea1.make();
System.out.println("");
tea2.make();
}
}
输出结果:
To be continue…
如果想学习Java工程化、高性能及分布式、深入浅出。性能调优、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级架构进阶群:180705916,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家