→23种设计模式大纲
责任链模式、命令模式、备忘录模式、状态模式
1)责任链模式
责任链模式:chain of responsibility Pattern
- 将请求的处理者连接成链,通常是线型,也可以是环型
- 请求者不需要直接关联所有的审批人
- 每个审批人只需要维护其直接后继的审批人
需要对审批何时终结做出处理,避免产生循环调用。
@Data
public class Purchase {
private String purchaseDays;
private String applyPerson;
}
//抽象审批类,持有下一个审批人(本类)的引用
abstract class Approver {
protected Approver nextApprover;
public void setApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
}
abstract void handlePurchase(Purchase purchase);
}
class Approver1 extends Approver {
@Override
void handlePurchase(Purchase purchase) {
System.out.println("Approver1 审批完毕");
//转交给下一个审批人审批
nextApprover.handlePurchase(purchase);
}
}
class Approver2 extends Approver {
@Override
void handlePurchase(Purchase purchase) {
System.out.println("Approver2 审批完毕");
//转交给下一个审批人审批
nextApprover.handlePurchase(purchase);
}
}
class Approver3 extends Approver {
@Override
void handlePurchase(Purchase purchase) {
//审批终结
System.out.println("Approver3 审批完毕 ,总流程结束!");
}
}
class Test{
public static void main(String[] args) {
Purchase purchase = new Purchase();
Approver approver1=new Approver1();
Approver approver2=new Approver2();
Approver approver3=new Approver3();
approver1.setApprover(approver2);
approver2.setApprover(approver3);
approver3.setApprover(approver3);
approver1.handlePurchase(purchase);
}
}
2)命令模式
命令模式:Command Pattern
命令主要涉及的角色如下:
- 抽象命令角色:Command,接口,定义执行命令的方法
- 具体命令实现类:Concrete Command,通过命令调用业务真正的执行者Receiver,持有Receiver引用
- 调用者:Invoker,请求的发出者,通常有多个Command对象的引用,并通过Command来调用真正的Receiver
- 接收者:Receiver,动作真正的执行者,不与请求发出者直接关联
调用链路: Invoker → Command A,Command B →Receiver A,Receiver B
//抽象命令接口
public interface Command {
void execute();
}
//具体命令1
class VegetableCommand implements Command{
//持有接收者引用
Receiver receiver;
VegetableCommand(Receiver receiver){
this.receiver=receiver;
}
@Override
public void execute() {
//调用接收者的方法执行真正的逻辑
receiver.makeVegetables();
}
}
//具体命令2
class MeatCommand implements Command{
//持有接收者引用
Receiver receiver;
MeatCommand(Receiver receiver){
this.receiver=receiver;
}
@Override
public void execute() {
//调用接收者的方法执行真正的逻辑
receiver.makeMeat();
}
}
class Receiver{
//真正的操作逻辑
public void makeVegetables(){
System.out.println("做蔬菜");
}
//真正的操作逻辑
public void makeMeat(){
System.out.println("做肉");
}
}
//Invoker 调用者
class Waiter{
//持有多个命令对象
private VegetableCommand vegetableCommand;
private MeatCommand meatCommand;
public Waiter(VegetableCommand vegetableCommand, MeatCommand meatCommand) {
this.vegetableCommand = vegetableCommand;
this.meatCommand = meatCommand;
}
public void executeVegetables(){
//通过命令间接控制Receiver
vegetableCommand.execute();
}
public void executeMeat(){
//通过命令间接控制Receiver
meatCommand.execute();
}
}
class Test{
public static void main(String[] args) {
Receiver receiver = new Receiver();
Waiter waiter = new Waiter(new VegetableCommand(receiver),new MeatCommand(receiver));
waiter.executeMeat();
waiter.executeVegetables();
}
}
- 当需要请求方和执行方完全解耦的时候,可以使用命令模式
- 当需要执行的逻辑很多时,会导致各个命令过多
- 可以结合组合的形式,封装多个命令,即宏命令的概念
- 结合备忘录模式可以实现命令的撤销和恢复
3)备忘录模式
备忘录模式:Memento Pattern
主要角色:
- 源发器:Originator,实体类,可以创建备忘录和使用备忘录恢复副本。
- 备忘录:Memento,储存实体的内部状态。
- 负责人:Caretaker,保存备忘录。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private String name;
private Integer sex;
private String address;
public Memento createMemento(){
return new Memento(name,sex,address);
}
public void restoreMemento(Memento memento){
this.name=memento.getName();
this.sex=memento.getSex();
this.address=memento.getAddress();
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Memento{
private String name;
private Integer sex;
private String address;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Caretaker {
Memento memento;
}
class Test{
public static void main(String[] args) {
Person person = new Person("zs", 1, "成都");
Memento memento = person.createMemento();
Caretaker caretaker = new Caretaker(memento);
person.setName("ll");
person.setSex(0);
person.setAddress("北京");
System.out.println(person);
person.restoreMemento(caretaker.getMemento());
System.out.println(person);
}
}
4)状态模式
状态模式:Status Pattern
//抽象状态类
public abstract class Status {
Context context;
Status(Context context) {
this.context = context;
}
abstract void work();
abstract void game();
}
class MorningStatus extends Status {
MorningStatus(Context context) {
super(context);
}
@Override
public void work() {
System.out.println("早上开始工作...到中午了");
context.setCurrentStatus(Context.noonStatus);
}
@Override
public void game() {
throw new RuntimeException("早上不能晚游戏");
}
}
class NoonStatus extends Status {
NoonStatus(Context context) {
super(context);
}
@Override
public void work() {
System.out.println("中午开始工作");
context.setCurrentStatus(Context.eveningStatus);
}
@Override
public void game() {
System.out.println("中午游戏一会儿");
}
}
class EveningStatus extends Status {
EveningStatus(Context context) {
super(context);
}
@Override
public void work() {
throw new RuntimeException("到晚上了该下班了");
}
@Override
public void game() {
System.out.println("晚上玩一会儿游戏");
context.setCurrentStatus(Context.morningStatus);
}
}
//上下类,存储当前状态,可以切换状态
class Context {
static Status morningStatus;
static Status noonStatus;
static Status eveningStatus;
static Status currentStatus;
public Context() {
morningStatus = new MorningStatus(this);
noonStatus = new NoonStatus(this);
eveningStatus = new EveningStatus(this);
}
public void setCurrentStatus(Status status) {
currentStatus = status;
}
public void work() {
currentStatus.work();
}
public void game() {
currentStatus.game();
}
}
class Test {
public static void main(String[] args) {
Context context=new Context();
context.setCurrentStatus(Context.morningStatus);
context.work();
context.game();
context.work();
context.game();
context.game();
}
}
- 状态模式是为了解决多种环境下的业务判断,将各环境下的处理逻辑抽象到单独的类里面
- 允许每个状态类里面的逻辑可以切换当前状态(存储在上下文里面)
- 需要一个类来保存所有的状态类(可以放在上下文里面)
- 简化了 if-else 逻辑判断的同时也会增加系统开销,环境越多,存储的类越多