文章目录
职责链模式
结构
- 抽象处理者:定义一个处理的请求的接口,一般设计为抽象类,维护处理者的顺序,达到链式调用
- 具体处理者:抽象处理者的子类,处理用户的请求,可以访问下一个处理者的对象,转发请求。
简单示例
例:某企业的供应链系统中,有一个采购审批系统,采购审批是分级进行的,根据采购金额的不同由不同层次的主管人员来审批。
//采购单类
public class PurchaseRequest {
private double amount;
private int number;
private String purpose;
public PurchaseRequest(double amount, int number, String purpose) {
this.amount = amount;
this.number = number;
this.purpose = purpose;
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getPurpose() {
return purpose;
}
public void setPurpose(String purpose) {
this.purpose = purpose;
}
}
// 审批者类
public abstract class Approver {
protected Approver successor;//定义后继对象
protected String name; //审批者姓名
public Approver(String name) {
this.name = name;
}
public void setSuccessor(Approver approver) {
this.successor = approver;
}
public abstract void processRequest(PurchaseRequest request);
}
// 具体处理者:主任
public class Director extends Approver {
public Director(String name) {
super(name);
}
// 具体请求处理方法
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < 50000) {
System.out.println("主任" + this.name + "审批采购单:" + request.getNumber() + ",金额:" + request.getAmount()
+ "元,采购目的:" + request.getPurpose() + ".");//处理请求
} else {
this.successor.processRequest(request);//转发请求
}
}
}
// 具体处理者:副董事长
public class VicePresident extends Approver {
public VicePresident(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < 100000) {
System.out.println("副董事长" + this.name + "审批采购单:" + request.getNumber() + ",金额:" + request.getAmount()
+ "元,采购目的:" + request.getPurpose() + ".");//处理请求
} else {
this.successor.processRequest(request);//转发请求
}
}
}
// 具体处理者:董事长类
public class President extends Approver {
public President(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < 500000) {
System.out.println("董事长" + this.name + "审批采购单:" + request.getNumber() + ",金额:" + request.getAmount()
+ "元,采购目的:" + request.getPurpose() + ".");//处理请求
} else {
this.successor.processRequest(request);//转发请求
}
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
Approver approver1 = new Director("主任");
Approver approver2 = new VicePresident("副董事长");
Approver approver3 = new President("董事长");
approver1.setSuccessor(approver2);
approver2.setSuccessor(approver3);
PurchaseRequest p = new PurchaseRequest(50001, 100001, "吃吃喝喝");
approver1.processRequest(p);
}
}
定义
责任链:避免讲请求的发送者和接收者耦合在一起,让职责分工明确,请求呈一条链往下传递,这条链可随时进行调整。
命令模式
结构
抽象命令类:抽象命令类一般是一个抽象类或接口,在其中声明了用于执行请求的exeute()等方法,通过这些方法可以调用请求接收者的相关操作。
具体命令类:具体命令类是抽象命令类的子类,实现了在抽象命令类中声明的方法,它对应具体的接收者对象,将接收者对象的动作绑定其中,具体命令类实现execute()方法时将调用接收者对象的相关操作(Action)
调用者:调用者即请求发送者,它通过命令对象来执行请求,一个调用者并不需要在设计时确定其接收者,因此它只与抽象命令类之间存在关联关系。在程序运行时可以将一个具体命令对象注入其中,再调用具体命令对象的execute()方法,从而实现间接调用请求接收者的相关操作。
接收者:接收者执行与请求相关的操作,具体实现对请求的业务处理。
简单示例
例:某系统提供一系列功能键,用户可以自定义功能键的功能,例如功能键FunctionButton可以用于退出系统,也可以用于显示帮助文档,用户可以通过修改配置文件改变功能键的用途,现使用命令模式设计该系统,使得功能键类与功能类之间解耦,可为同一个功能键设置不同的功能
// 功能键类
public class FunctionButton {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void click() {
System.out.println("单击功能键:");
command.execute();
}
}
// 抽象命令类
public abstract class Command {
public abstract void execute();
}
// 退出命令类
public class ExitCommand extends Command {
private SystemExitClass systemExitClass = new SystemExitClass();
@Override
public void execute() {
systemExitClass.exit();
}
}
// 帮助命令类
public class HelpCommand extends Command{
private DisplayHelpClass displayHelpClass = new DisplayHelpClass();
@Override
public void execute() {
displayHelpClass.display();
}
}
// 退出系统模拟实现类
public class SystemExitClass {
public void exit() {
System.out.println("退出系统。");
}
}
// 帮助文档模拟实现类
public class DisplayHelpClass {
public void display() {
System.out.println("显示帮助文档!");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
FunctionButton fb = new FunctionButton();
Command command = new ExitCommand();
fb.setCommand(command);
fb.click();
}
}
定义
将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。
扩展
- 将command换成队列或者时集合,可以实现一对多的请求
- 在command中使用队列,可以实现撤销操作
解释器模式
结构
抽象表达式:在抽象表达式中声明了抽象的解释操作,它是所有终结符表达式和非终结符表达式的公共父类
终结符表达式:终结符表达式时抽象表达式的子类,它实现了与文法中的终结符相关联的解释操作,在句子中的每一个终结符都是该类的一个实例,通常在一个解释器模式中只有少数几个终结符表达式类,他们的实例可以通过非终结符表达式组成较为复杂的句子
非终结符表达式:非终结符表达式也是抽象表达式的子类,它实现了文法中非终结符的解释操作,由于在非终结符表达式中可以包含终结符表达式,也可以继续包含非终结表达式,因此其解释操作一般通过递归的方式完成
环境类:上下文类,它用于存储解释器之外的一些全局信息,通常它临时存储需要解释的语句。
简单示例
例:有一套机器人控制程序,每一个指令对应一个表达式,该表达式可以是简单表达式也可以是复合表达式,每一个简单表达式由移动方向,移动方式和移动距离3部分组成,其中移动方向包括上、下、 左、右;移动方式包括移动和快速移动;移动距离为一个正整数。两个表达式之间可以通过与连接形成复合表达式。
用户通过图形化的设置界面操作可以创建一个机器人控制指令,机器人在收到指令后将按照指令的设置进行移动,例如输入控制指令“up move 5"则向上移动5个单位;输入控制指令”down run 10 and left move 20“,则”向下快速移动10个单位再向左移动20个单位“
// 抽象节点类,充当抽象表达式角色
public abstract class AbstractNode {
public abstract String interpret();
}
// and节点类,充当非终结符表达式角色
public class AndNode extends AbstractNode {
private AbstractNode legt;
private AbstractNode right;
public AndNode(AbstractNode legt, AbstractNode right) {
this.legt = legt;
this.right = right;
}
@Override
public String interpret() {
return legt.interpret() + "再" + right.interpret();
}
}
// 简单句子节点类,充当非终结符表达式角色
public class SentenceNode extends AbstractNode {
private AbstractNode direction;
private AbstractNode action;
private AbstractNode distance;
public SentenceNode(AbstractNode direction, AbstractNode action, AbstractNode distance) {
this.direction = direction;
this.action = action;
this.distance = distance;
}
@Override
public String interpret() {
return direction.interpret() + action.interpret() + distance.interpret();
}
}
// 方向节点类,充当终结符表达式角色
public class DirecitonNode extends AbstractNode {
private String direction;
public DirecitonNode(String direction) {
this.direction = direction;
}
@Override
public String interpret() {
switch (direction) {
case "up": return "向上";
case "down": return "向下";
case "left": return "向左";
case "right": return "向右";
default: return "无效指令";
}
}
}
// 动作节点类,充当终结符表达式角色
public class ActionNode extends AbstractNode {
private String action;
public ActionNode(String action) {
this.action = action;
}
@Override
public String interpret() {
switch (action) {
case "move" : return "移动";
case "run" : return "快速移动";
default:return "无效指令";
}
}
}
// 距离节点类,充当终结符表达式角色
public class DistanceNode extends AbstractNode {
private String distance;
public DistanceNode(String distance) {
this.distance = distance;
}
@Override
public String interpret() {
return this.distance;
}
}
// 指令处理类,提供相应的方法输入指令处理。
public class InstructionHandle {
private AbstractNode node;
public void hanlde(String instruction) {
AbstractNode left = null, right = null;
AbstractNode direciton = null, aciont = null, disctance = null;
Stack<AbstractNode> stack = new Stack<>();// 存储语法树
String[] words = instruction.split(" ");
for (int i = 0; i < words.length; i++) {
if (words[i].equalsIgnoreCase("and")) {
String word1 = words[++i];
direciton = new DirecitonNode(word1);
String word2 = words[++i];
aciont = new ActionNode(word2);
String word3 = words[++i];
disctance = new DistanceNode(word3);
right = new SentenceNode(direciton,aciont,disctance);
stack.push(new AndNode(left, right));
} else {
String word1 = words[i];
direciton = new DirecitonNode(word1);
String word2 = words[++i];
aciont = new ActionNode(word2);
String word3 = words[++i];
disctance = new DistanceNode(word3);
left = new SentenceNode(direciton, aciont, disctance);
stack.push(left);
}
}
this.node = stack.pop();
}
public String output() {
String result = node.interpret();
return result;
}
}
public class Client {
public static void main(String[] args) {
String instruction = "down run 10 and left move 20";
InstructionHandle handle = new InstructionHandle();
handle.hanlde(instruction);
String outString = handle.output();
System.out.println(outString);
}
}
定义
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
中介者模式
结构
抽象中介者:定义一个接口,该接口用于与各同事对象之间进行通信
具体中介者类:它是抽象中介者的子类,通过协调各个人员对象来实现协作行为,它维持了对各个人员对象的引用
抽象同事类:它定义各个同事类共有的方法,并声明了一些抽象方法供子类实现,同时它维持了一个对抽象中介者类的引用,其子类可以通过该引用与中介者通信
具体同事类:抽象同事类的子类,每个同事对象需要和其他同事对象时先与中介者通信,通过中介者间接完成与其他同事类的通信,在具体同事类中实现了在抽象同事类中国声明的抽象方法。
简单示例
例:有一套客户信息管理模块,界面有按钮,下拉框,列表,输入框,当删除一个人的时候,要从下拉框也删除,如果增加一个人时,列表,下拉框中同时也同增加。
// 抽象中介者类
public abstract class Mediator {
public abstract void componentChanged(Component c);
}
// 具体中介者类
public class ConcreteMediator extends Mediator {
// 维持对各个同事对象的引用
public Button addButton;
public List list;
public TextBox textBox;
public ComboBox comboBox;
@Override
public void componentChanged(Component c) {
if (c == addButton) {
System.out.println("---单击增加按钮---");
list.update();
comboBox.update();
textBox.setText();
} else if (c == list) {
System.out.println("---从列表框选择客户---");
comboBox.select();
textBox.setText();
} else {
System.out.println("---从组合框选择客户---");
comboBox.select();
textBox.setText();
}
}
}
//抽象组件类,充当抽象人员类
public abstract class Component {
protected Mediator mediator;
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
// 转发调用
public void changed() {
mediator.componentChanged(this);
}
public abstract void update();
}
// 按钮类
public class Button extends Component {
@Override
public void update() {
// 按钮不产生反应
}
}
// 列表框类
public class List extends Component {
@Override
public void update() {
System.out.println("列表框增加一项:张无忌.");
}
public void select() {
System.out.println("列表框选中项:小龙女.");
}
}
// 组合框类
public class ComboBox extends Component {
@Override
public void update() {
System.out.println("组合框增加一项:张无忌");
}
public void select(){
System.out.println("组合框选中项目:小龙女.");
}
}
// 文本框类,充当具体人员类
public class TextBox extends Component {
@Override
public void update() {
System.out.println("客户信息增加成功后文本框清空");
}
public void setText() {
System.out.println("文本框显示:小龙女");
}
}
public class Client {
public static void main(String[] args) {
// 定义中介者对象
ConcreteMediator mediator = new ConcreteMediator();
// 定义同事对象
Button bt = new Button();
List list = new List();
ComboBox cb = new ComboBox();
TextBox tb = new TextBox();
bt.setMediator(mediator);
list.setMediator(mediator);
cb.setMediator(mediator);
tb.setMediator(mediator);
mediator.addButton = bt;
mediator.list = list;
mediator.comboBox = cb;
mediator.textBox = tb;
bt.changed();
System.out.println("-------------");
list.changed();
}
}
输出:
---单击增加按钮---
列表框增加一项:张无忌.
组合框增加一项:张无忌
文本框显示:小龙女
-------------
---从列表框选择客户---
组合框选中项目:小龙女.
文本框显示:小龙女
定义
定义一个对象来封装一系列对象的交互,中介者模式使得各对象之间不需要显式的相互引用,从而使其耦合松散,并且用户可以独立的改变他们之间的交互。
备忘录模式
结构
- 原发器:原发器是一个普通类,它通过创建一个备忘录来存储当前内部状态,也可以使用备忘录来恢复其内部状态,一般将系统中需要保存内部状态的类设计为原发器
- 备忘录:用于存储原发器的内部状态,根据原发器来决定保存哪些内部状态,备忘录的设计一般可以参考原发器的设计,根据实际需要确定备忘录类中的属性。
- 负责人:负责保存备忘录,但是不能对备忘录的内容进行操作或者检查,在负责人类中可以存储一个或多个备忘录对象,它只负责存储对象,而不能修改对象。
简单示例
例:实现象棋中的悔棋功能
// 象棋棋子类,充当原发器
public class Chessman {
private String label;
private int x;
private int y;
public Chessman(String label, int x, int y) {
this.label = label;
this.x = x;
this.y = y;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
// 保存状态
public ChessmanMemento save() {
return new ChessmanMemento(this.label, this.x, this.y);
}
public void restore(ChessmanMemento memento) {
this.label = memento.getLabel();
this.x = memento.getX();
this.y = memento.getY();
}
}
// 象棋棋子备忘录类,充当备忘录类
public class ChessmanMemento {
private String label;
private int x;
private int y;
public ChessmanMemento(String label, int x, int y) {
this.label = label;
this.x = x;
this.y = y;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
// 象棋棋子备忘录管理类,充当负责人
public class MementoCaretaker {
private ChessmanMemento memento;
public ChessmanMemento getMemento() {
return memento;
}
public void setMemento(ChessmanMemento memento) {
this.memento = memento;
}
}
public class Client {
public static void main(String[] args) {
MementoCaretaker caretaker = new MementoCaretaker();
Chessman chessman = new Chessman("车", 1, 1);
display(chessman);
caretaker.setMemento(chessman.save());
chessman.setY(4);
display(chessman);
caretaker.setMemento(chessman.save());
chessman.setX(5);
display(chessman);
System.out.println("----悔棋----");
chessman.restore(caretaker.getMemento());
display(chessman);
}
public static void display(Chessman chessman) {
System.out.println("棋子" + chessman.getLabel() + "当前位置:第" + chessman.getX() + "行,第" + chessman.getY() + "列");
}
}
棋子车当前位置:第1行,第1列
棋子车当前位置:第1行,第4列
棋子车当前位置:第5行,第4列
----悔棋----
棋子车当前位置:第1行,第4列
定义
在不破坏封装的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原来保存的状态。。
扩展
对于管理者来讲,使用集合或者队列,可以多元化的实现–多次撤销、撤销到初始状态等等。
观察者模式
结构
- 目标:目标又称为主题,是被观察的对象,在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify(),目标类可以是接口,也可以是抽象类或者具体类。
- 具体目标:具体目标是目标类的子类,它通常包含有经常发生改变的数据,当它的状态发生改变时将向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法。无需扩展目标类,则具体目标类可以省略
- 观察者:观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者
- 具体观察者:在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。通常在实现时可以调用具体目标类attach()方法将自己添加到目标类的集合中或删除
简单示例
例:在一个多人联机游戏中,多个玩家可以组成同盟战队,当战队中一个队员收到攻击时,要给其他队员发出通知,盟友收到通知后将做出响应。
// 指挥部类,充当抽象目标类
public abstract class AllyControlCenter {
protected String allyName;// 战队名称
protected ArrayList<Observer> players = new ArrayList<>();// 存储战队队员
public String getAllyName() {
return allyName;
}
public void setAllyName(String allyName) {
this.allyName = allyName;
}
// 注册方法
public void join(Observer obs) {
System.out.println(obs.getName() + "加入" + this.allyName + "战队");
players.add(obs);
}
// 注销方法
public void quit(Observer obs) {
System.out.println(obs.getName() + "退出" + this.allyName + "战队");
players.remove(obs);
}
// 声明抽象通知方法
public abstract void notifyObserver(String name);
}
// 具体指挥部类,充当具体目标类
public class ConcreteAllyControlCenter extends AllyControlCenter {
public ConcreteAllyControlCenter(String allyName) {
System.out.println(allyName + "战队组件成功");
System.out.println("-------------------------");
this.allyName = allyName;
}
@Override
public void notifyObserver(String name) {
System.out.println(this.allyName + "战队紧急通知,盟友" + name + "遭受攻击");
for (Observer obs: players) {
if (!(obs.getName().equalsIgnoreCase(name))){
obs.help();
}
}
}
}
// 抽象观察者
public interface Observer {
public String getName();
public void setName(String name);
public void help(); // 声明支援盟友方法
public void beAttacked(AllyControlCenter allyControlCenter); // 声明遭受攻击方法
}
// 战队成员类,充当具体观察者类
public class Players implements Observer {
private String name;
public Players(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public void help() {
System.out.println("坚持住!!!" + this.name + "正在路上");
}
@Override
public void beAttacked(AllyControlCenter allyControlCenter) {
System.out.println(this.name + "被攻击");
allyControlCenter.notifyObserver(name);
}
}
public class Client {
public static void main(String[] args) {
AllyControlCenter acc = new ConcreteAllyControlCenter("金庸群侠");
Observer p1, p2, p3,p4;
p1 = new Players("杨过");
p2 = new Players("令狐冲");
p3 = new Players("张无忌");
p4 = new Players("段誉");
acc.join(p1);
acc.join(p2);
acc.join(p3);
acc.join(p4);
p1.beAttacked(acc);
}
}
金庸群侠战队组件成功
-------------------------
杨过加入金庸群侠战队
令狐冲加入金庸群侠战队
张无忌加入金庸群侠战队
段誉加入金庸群侠战队
杨过被攻击
金庸群侠战队紧急通知,盟友杨过遭受攻击
坚持住!!!令狐冲正在路上
坚持住!!!张无忌正在路上
坚持住!!!段誉正在路上
定义
定义对象之间的一种一对多的依赖关系,使得每当一个对象状态发生改变其相关依赖对象皆得到通知并被自动更新。
扩展
java.until.Observable接口支持观察者模式
状态模式
结构
- 环境类:又称为上下文类,它是拥有多种状态的对象。由于环境类的状态存在多样性且在不同状态下对象的行为有所不同,因此将状态独立出去形成单独的状态类。在环境中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时它是一个state子类的对象
- 抽象状态类:它用于定义一个接口以封装与环境类的一个特定状态相关的行为,在抽象状态类中声明了各种不同状态队员的方法,而在其子类中实现了这些方法,由于不同状态下对象的行为可能不同,因此在不同子类中方法的可能存在不同,相同的方法可以写在抽象状态类中。
- 具体状态类:它是抽象状态类的子类,每一个子类实现一个环境类的一个状态相关的行为,每一个具体状态类对应环境的一个具体状态,不同的具体状态类的行为有所不同。
简单示例
例:有一个信用卡业务系统,账务余额大于0的时候,为正常状态,可以存钱也可以取钱
当账户余额小于0并且大于-2000时,状态为透支状态,可以存款也可以取款,按天计算利息
当账户余额等于-2000,状态为受限状态,只能存款,不能取款,并且按天计算利息
// 银行账户,充当环境类
public class Account {
private AccountState state;
private String owner;
private double balance = 0;
public Account(double init, String owner) {
this.balance = init;
this.owner = owner;
this.state = new NormalState(this);
System.out.println(this.owner + "开户,初始金额为" + init);
System.out.println("--------------------");
}
public void setState(AccountState state) {
this.state = state;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public void deposit(double amount) {
System.out.println(this.owner + "存款" + amount);
state.deposit(amount);
System.out.println("现在余额为" + this.balance);
System.out.println("现在账户状态为" + this.state.getClass().getName());
System.out.println("-------------------------");
}
public void withdraw(double amount) {
System.out.println(this.owner + "取款" + amount);
state.widthdraw(amount);
System.out.println("现在余额为" + this.balance);
System.out.println("现在账户状态为" + this.state.getClass().getName());
System.out.println("-------------------------");
}
public void computeInterest() {
state.computeInterest();
}
}
// 账户装态类,充当抽象状态类
public abstract class AccountState {
protected Account acc;
public abstract void deposit(double amount);
public abstract void widthdraw(double amount);
public abstract void computeInterest();
public abstract void stateCheck();
}
// 正常状态类,充当具体状态类
public class NormalState extends AccountState {
public NormalState(Account account) {
this.acc = account;
}
public NormalState(AccountState state) {
this.acc = state.acc;
}
@Override
public void deposit(double amount) {
acc.setBalance(acc.getBalance() + amount);
stateCheck();
}
@Override
public void widthdraw(double amount) {
acc.setBalance(acc.getBalance() - amount);
stateCheck();
}
@Override
public void computeInterest() {
System.out.println("正常状态,无需支付利息");
}
@Override
public void stateCheck() {
if (acc.getBalance() > -2000 && acc.getBalance() <= 0) {
acc.setState(new OverdraftState(this));
} else if (acc.getBalance() == -2000) {
acc.setState(new RestrictedState(this));
} else if (acc.getBalance() < -2000) {
System.out.println("操作受限");
}
}
}
// 透支状态类,充当具体装态类
public class OverdraftState extends AccountState {
public OverdraftState(AccountState state) {
this.acc = state.acc;
}
@Override
public void deposit(double amount) {
acc.setBalance(acc.getBalance() + amount);
stateCheck();
}
@Override
public void widthdraw(double amount) {
acc.setBalance(acc.getBalance() - amount);
stateCheck();
}
@Override
public void computeInterest() {
System.out.println("计算利息");
}
@Override
public void stateCheck() {
if (acc.getBalance() > 0) {
acc.setState(new NormalState(this));
} else if (acc.getBalance() == -2000) {
acc.setState(new RestrictedState(this));
} else if (acc.getBalance() < 2000) {
System.out.println("操作受限");
}
}
}
// 受限状态类,充当具体状态类
public class RestrictedState extends AccountState {
public RestrictedState(Account account) {
this.acc = account;
}
public RestrictedState(AccountState state) {
this.acc = state.acc;
}
@Override
public void deposit(double amount) {
acc.setBalance(acc.getBalance() + amount);
stateCheck();
}
@Override
public void widthdraw(double amount) {
System.out.println("账号受限,取款失败");
}
@Override
public void computeInterest() {
System.out.println("计算利息");
}
@Override
public void stateCheck() {
if (acc.getBalance() > 0) {
acc.setState(new NormalState(this));
} else if (acc.getBalance() > -2000) {
acc.setState(new OverdraftState(this));
}
}
}
public class Client {
public static void main(String[] args) {
Account acc = new Account(0.0, "段誉");
acc.deposit(1000);
acc.withdraw(2000);
acc.deposit(3000);
acc.withdraw(4000);
acc.withdraw(1000);
acc.computeInterest();
}
}
段誉开户,初始金额为0.0
--------------------
段誉存款1000.0
现在余额为1000.0
现在账户状态为NormalState
-------------------------
段誉取款2000.0
现在余额为-1000.0
现在账户状态为OverdraftState
-------------------------
段誉存款3000.0
现在余额为2000.0
现在账户状态为NormalState
-------------------------
段誉取款4000.0
现在余额为-2000.0
现在账户状态为RestrictedState
-------------------------
段誉取款1000.0
账号受限,取款失败
现在余额为-2000.0
现在账户状态为RestrictedState
-------------------------
计算利息
定义
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类
策略模式
结构
- 环境类:环境类是使用算法的角色,它在解决某个问题(即实现某个功能)时剋采用多种策略,在环境中维持一个对抽象策略类的引用实例,用于定义所采用的策略
- 抽象策略类:抽象策略类为所支持的算法声明了抽象方法,是所有策略类的父类,它可以是抽象类或具体类,也可以是接口。环境类通过抽象策略类中声明的方法在运行时调用具体策略类中实现的算法
- 具体策略类:具体策略类实现了在抽象策略类中声明的算法,在运行时具体策略类将覆盖在环境类中定义的抽象策略类对象,使用一种具体的算法实现某个业务功能
简单示例
例:某电影售票系统,具体打折方案如下
1:学生打八折
2:10岁一下的儿童减免10元
3:VIP用户享受半价,并且可以积分。
// 电影票类,充当环境类
public class MovieTicket {
private double price;
private Discount discount;
public void setPrice(double price) {
this.price = price;
}
public void setDiscount(Discount discount) {
this.discount = discount;
}
public double getPrice() {
return discount.calculate(this.price);
}
}
// 折扣类,充当抽象策略类
public interface Discount {
public double calculate(double price);
}
// 学生票折扣类,充当具体策略类
public class StudentDisount implements Discount{
private final double DISCOUNT = 0.8;
@Override
public double calculate(double price) {
System.out.println("学生票:");
return price * DISCOUNT;
}
}
// 儿童票折扣类,充当具体策略类
public class ChildrenDiscount implements Discount {
@Override
public double calculate(double price) {
System.out.println("儿童票:");
return price - 10;
}
}
// VIP折扣类
public class VIPDiscount implements Discount{
@Override
public double calculate(double price) {
System.out.println("VIP票:");
System.out.println("增加积分");
return price * 0.5;
}
}
public class Client {
public static void main(String[] args) {
MovieTicket movieTicket = new MovieTicket();
double oriPrice = 60;
double curPrice;
movieTicket.setPrice(oriPrice);
System.out.println("原始价为:" + oriPrice);
System.out.println("---------------------");
Discount discount = new VIPDiscount();
movieTicket.setDiscount(discount);
System.out.println("折扣价为:" + movieTicket.getPrice());
}
}
原始价为:60.0
---------------------
VIP票:
增加积分
折扣价为:30.0
定义
定义一系列算法,将每一个算法封装起来,并让他们可以相互替换,策略模式让算法可以独立于使用它的客户而变化
模板方法模式
结构
- 抽象类:在抽象类中定义一些列基本操作,这些基本操作可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤,同时在抽象类中实现了一个模板方法,用于定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法
- 具体子类:它是抽象类的子类,用于实现在父类中声明的抽象基本操作以完成子类特性算法的步骤,也可以覆盖在父类中已经实现的基本操作步骤
简单示例
例:某银行有一个利息计算模块,利息计算流程如下
1:根据账号和密码验证用户信息,如果用户信息错误,系统显示出错提示
2:如果用户信息正确,则根据用户类型的不同使用不同的利息计算公司计算利息
3:系统显示利息
// 账户类,充当抽象类
public abstract class Account {
public boolean validate(String account, String password) {
System.out.println("账户:" + account);
System.out.println("密码:" + password);
if (account.equalsIgnoreCase("张无忌") && password.equalsIgnoreCase("123456")) {
return true;
} else {
return false;
}
}
public abstract void calculateInterest();
public void display() {
System.out.println("显示利息!");
}
// 模板方法
public void handle(String account, String password) {
if (!validate(account, password)) {
System.out.println("账号或密码错误!");
return;
}
calculateInterest();
display();
}
}
// 活期账户类,充当具体子类
public class CurrentAccount extends Account {
@Override
public void calculateInterest() {
System.out.println("按活期利率计算利息");
}
}
// 定期账户类,充当具体子类
public class SavingAccount extends Account {
@Override
public void calculateInterest() {
System.out.println("按定期利率计算利息");
}
}
public class Client {
public static void main(String[] args) {
Account account = new CurrentAccount();
account.handle("张无忌", "123456");
}
}
账户:张无忌
密码:123456
按活期利率计算利息
显示利息!
定义
定义一个操作中算法的框架,而将一些步骤延迟到子类中,模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特性步骤
扩展
钩子方法
访问者模式
结构
- 抽象访问者:为对象结构中的每一个具体元素类声明一个访问操作,从这个操作的名称或参数类型可以清楚的知道需要访问的具体元素的类型,具体访问者需要实现这些操作方法,定义对这些元素的访问操作
- 具体访问者:具体访问者实现了每个由抽象访问者声明的操作,每个操作都用于访问对象结构中一种类型的元素
- 抽象元素:抽象元素一般都是抽象类或者接口,它声明了一个accept()方法,用于接收访问者的访问操作,该方法通常由一个抽象访问者作为参数
- 具体元素:具体元素实现了accept()方法,在accept()方法中调用访问者的访问方法以便完成对一个元素的操作
- 对象结构:对象结构是一个元素的集合,它用于存放元素对象,并且提供了遍历其内部元素的方法,对象结构可以结合组合模式来实现,也可以是一个简单的结合对象。
简单示例
例:有一个员工信息管理系统,该公司员工包括正式员工和临时工,每周人力资源和财务部等部门都需要对员工数据进行汇总,汇总数据包括员工工作时间、员工工资等。该公司的基本制度为如下:
1:正式员工每周工作40小时,不同级别,不同部门的员工每周基本工资不同,如果超出40小时,超出部分按照100元每小时作为加班费,如果少于40小时,所缺时间按照请假处理,请假所扣工资为80元每小时
2:临时工按照工时计算公司,
人力资源部需要汇总员工工作时间,财务部负责计算员工工资
// 员工类 充当抽象元素类
public interface Employee {
public void accept(Department handler);
}
// 全职员工类,充当具体元素类
public class FullTimeEmployee implements Employee {
private String name;
private double weeklyWage;
private int workTime;
public FullTimeEmployee(String name, double weeklyWage, int workTime) {
this.name = name;
this.weeklyWage = weeklyWage;
this.workTime = workTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getWeeklyWage() {
return weeklyWage;
}
public void setWeeklyWage(double weeklyWage) {
this.weeklyWage = weeklyWage;
}
public int getWorkTime() {
return workTime;
}
public void setWorkTime(int workTime) {
this.workTime = workTime;
}
@Override
public void accept(Department handler) {
handler.visit(this);
}
}
// 兼职员工类,充当具体元素类
public class PartTimeEmployee implements Employee {
private String name;
private double hourWage;
private int workTime;
public PartTimeEmployee(String name, double hourWage, int workTime) {
this.name = name;
this.hourWage = hourWage;
this.workTime = workTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getHourWage() {
return hourWage;
}
public void setHourWage(double hourWage) {
this.hourWage = hourWage;
}
public int getWorkTime() {
return workTime;
}
public void setWorkTime(int workTime) {
this.workTime = workTime;
}
@Override
public void accept(Department handler) {
handler.visit(this);
}
}
// 部门类,充当抽象访问者类
public abstract class Department {
public abstract void visit(FullTimeEmployee employee);
public abstract void visit(PartTimeEmployee employee);
}
// 财务部类,充当具体访问者类
public class FADepartment extends Department{
// 财务部对全职员工的访问
@Override
public void visit(FullTimeEmployee employee) {
int workTime = employee.getWorkTime();
double weekWage = employee.getWeeklyWage();
if (workTime > 40) {
weekWage = workTime + (workTime - 40) * 100;
} else if (workTime < 40){
weekWage = workTime + (40 - workTime) * 80;
if (weekWage < 0) {
weekWage = 0;
}
}
System.out.println("正式员工" + employee.getName() + "实际工资为:" + weekWage + "元。");
}
// 财务部去兼职员工的访问
@Override
public void visit(PartTimeEmployee employee) {
int workTime = employee.getWorkTime();
double hourWage = employee.getHourWage();
System.out.println("临时工" + employee.getName() + "实际工资为:" + workTime * hourWage + "元。");
}
}
// 人力资源类,充当具体访问者类
public class HRDepartment extends Department {
@Override
public void visit(FullTimeEmployee employee) {
int workTime = employee.getWorkTime();
System.out.println("正式员工:" + employee.getName() + "实际工作时间为:" + workTime + "小时。");
}
@Override
public void visit(PartTimeEmployee employee) {
int workTime = employee.getWorkTime();
System.out.println("临时工:" + employee.getName() + "实际工作时间为:" + workTime + "小时。");
}
}
// 员工列表类,充当对象结构
public class EmployeeList {
private List<Employee> list = new ArrayList<>();
public void addEmployee (Employee employee) {
list.add(employee);
}
// 遍历访问员工集合中的每一个员工对象
public void accept(Department handler) {
for (Employee employee : list) {
employee.accept(handler);
}
}
}
public class Client {
public static void main(String[] args) {
EmployeeList list = new EmployeeList();
Employee f1, f2, f3, p1, p2;
f1 = new FullTimeEmployee("张无忌",3200.0,45);
f2 = new FullTimeEmployee("杨过",2000.0,40);
f3 = new FullTimeEmployee("段誉",2400.0,38);
p1 = new PartTimeEmployee("洪七公",80.0,20);
p2 = new PartTimeEmployee("郭靖",60.0,18);
list.addEmployee(f1);
list.addEmployee(f2);
list.addEmployee(f3);
list.addEmployee(p1);
list.addEmployee(p2);
Department dep =new FADepartment();
list.accept(dep);
}
}
定义
表示一个作用于某对象结构中的各个元素的操作,访问者模式让用户可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
扩展
访问者模式通常和组合模式一起使用。