设计模式--行为型模式
目录模板方法模式
定义
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。(类行为型模式)
结构
-
抽象类:负责给出一个算法的轮廓和骨架,它由一个模板方法和若干个基本方法构成。
- 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法
- 基本方法:是实现算法各步骤的方法,是模板方法的组成部分。分为三类:
- 抽象方法:一个抽象方法有抽象类声明,由具体子类实现
- 具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖或直接继承
- 钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和想要子类重写的空方法两种。一般的钩子方法是用于判断的逻辑方法,类名一般是isXxx,返回值是boolean类型
-
具体子类:实现抽象类中所定义的抽象方法和钩子方法,他们是一个顶级逻辑的组成部分。
举个栗子
/*
炒菜的栗子,步骤确定,炒的菜不确定。
*/
/**
* @author strind
* @version 1.0
* @description 模板方法
* @date 2024/2/6 10:00
*/
public class fry {
public static void main(String[] args) {
FryTomato fryTomato = new FryTomato();
fryTomato.cookProcess();
System.out.println("=====================");
FryPotato fryPotato = new FryPotato();
fryPotato.cookProcess();
}
}
// 抽象类
abstract class abstractFry{
// 模板方法,子类不能重写
public final void cookProcess(){
pourOil();
heatOil();
pourVeg(); //由于是抽象类,子类必重写,所以调用的是子类的该方法,实现反转控制
fry();
}
public void pourOil(){
System.out.println("倒油");
}
public void heatOil(){
System.out.println("热油");
}
// 抽象方法
public abstract void pourVeg();
public void fry(){
System.out.println("开始炒菜");
}
}
class FryTomato extends abstractFry{
@Override
public void pourVeg() {
System.out.println("加入西红柿");
}
}
class FryPotato extends abstractFry{
@Override
public void pourVeg() {
System.out.println("加入土豆");
}
}
策略模式
定义
该模式定义了一系列算法,并将每个算法封装起来,使得他们之间可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,通过对算法的封装,使使用算法与设计算法的责任分开,并委派给不同的对象对这些算法进行管理。
结构
- 抽象策略类:通常由一个接口或抽象类实现,此角色给出所有的具体策略类所需的接口
- 具体策略类:实现了抽象策略类的接口,提供具体的算法实现或行为
- 环境类:持有一个策略类的引用,最终给客户端调用
举个栗子
/**
* @author strind
* @version 1.0
* @description 策略模式
* @date 2024/2/6 10:23
*/
public class test {
public static void main(String[] args) {
// 在A,B, C 之间相互切换
SaleMan saleMan = new SaleMan(new StrategyA());
saleMan.saleStrategy();
}
}
// 抽象策略类
interface Strategy{
void show();
}
// 具体策略类
class StrategyA implements Strategy{
@Override
public void show() {
System.out.println("买一送一");
}
}
class StrategyB implements Strategy{
@Override
public void show() {
System.out.println("满100送50");
}
}
class StrategyC implements Strategy{
@Override
public void show() {
System.out.println("满200任选一件价值100的礼品");
}
}
// 环境类
class SaleMan{
private Strategy strategy;
public SaleMan(Strategy strategy) {
this.strategy = strategy;
}
public void saleStrategy(){
strategy.show();
}
}
// 可以用于消除大量的if-else语句
命令模式
定义
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储,传递,调用,增加与管理。
结构
- 抽象命令角色:定义命令的接口,声明执行的方法
- 具体命令角色:实现抽象命令接口,通常持有接收者,并调用接收者的功能来完成命令要执行的操作
- 接收者角色:真正执行命令的对象,任何类都可以成为接收者,只要它能完成响应的功能
- 请求者:要求命令对象执行请求,通常持有命令对象,由客户端除法命令并开始执行相关操作,是使用命令对象的入口。
举个栗子
/**
* @author strind
* @version 1.0
* @description
* @date 2024/2/6 10:57
*/
public class test {
public static void main(String[] args) {
Order order1 = new Order();
order1.setTabNum(1);
order1.setFood("111",1);
order1.setFood("222",2);
order1.setFood("333",3);
Order order2 = new Order();
order2.setTabNum(2);
order2.setFood("444",4);
order2.setFood("555",5);
order2.setFood("666",6);
Command command1 = new OrderCommand(new cook(),order1);
Command command2 = new OrderCommand(new cook(),order2);
Waiter waiter = new Waiter();
waiter.setCommond(command1);
waiter.send_commond();
System.out.println();
waiter.setCommond(command2);
waiter.send_commond();
}
}
class Order{
private int tabNum; // 桌号
private Map<String,Integer> foodDir = new HashMap<>();
public int getTabNum() {
return tabNum;
}
public void setTabNum(int tabNum) {
this.tabNum = tabNum;
}
public Map<String, Integer> getFoodDir() {
return foodDir;
}
public void setFood(String name, int num) {
foodDir.put(name,num);
}
}
//
class cook{
public void makeFood(String name, int num){
System.out.println(" 厨师做了" + num + "份" + name);
}
}
// 抽象的命令类
interface Command{
void execute();
}
// 具体的命令类
class OrderCommand implements Command{
// 命令接收者
private cook cook;
private Order order;
public OrderCommand(cook cook, Order order) {
this.cook = cook;
this.order = order;
}
@Override
public void execute() {
System.out.println(order.getTabNum() + "桌的订单:");
Set<String> keys = order.getFoodDir().keySet();
for (String key : keys) {
cook.makeFood(key,order.getFoodDir().get(key));
}
System.out.println(order.getTabNum() + "桌已完成");
}
}
// 请求者
class Waiter{
// 持有多个命令对象
private List<Command> commonds = new ArrayList<>();
public void setCommond(Command commond){
commonds.add(commond);
}
// 发送命令
public void send_commond(){
if (!commonds.isEmpty()) {
System.out.println("订单来了");
for (Command commond : commonds) {
commond.execute();
}
commonds.clear();
} else {
System.out.println("嗯?????");
}
}
}
实现的是:请求者与接收者之间的耦合;(在栗子中,就是服务员与厨师的解耦。一般而言,会把厨师聚合到服务员类中,直接调用厨师的方法,耦合较高)
责任链模式
定义
为了避免请求的发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一个对象记住下一个对象的引用而连成一条链,当有请求发生时,可将请求沿着链传递,直到可以处理为止。
结构
- 抽象处理者:定义处理请求的接口,包含抽象处理方法和后继连接
- 具体的处理者:实现抽象处理方法,判断是否处理请求,能则处理,反之传递
- 客户:创建处理链,向链头提交请求。
举个例子
/*
公司请假
*/
/**
* @author strind
* @version 1.0
* @description 责任链模式
* @date 2024/2/6 11:41
*/
public class test {
public static void main(String[] args) {
LeaveRequest leaveRequest = new LeaveRequest("TOM", 2, "病假");
GroupLeader groupLeader = new GroupLeader();
// 创建责任链
Manager manager = new Manager();
GeneralManager generalManager = new GeneralManager();
groupLeader.setNextHandler(manager);
manager.setNextHandler(generalManager);
// 提交请求
groupLeader.submit(leaveRequest);
}
}
class LeaveRequest{
private String name;
private int day;
private String content;
public LeaveRequest(String name, int day, String content) {
this.name = name;
this.day = day;
this.content = content;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
abstract class handler{
protected static final int DAY_ONE = 1;
protected static final int DAY_THREE = 3;
protected static final int DAY_SEVEN = 7;
private int dayStart;
private int dayEnd;
private handler nextHandler;
public handler(int dayStart) {
this.dayStart = dayStart;
}
public handler(int dayStart, int dayEnd) {
this.dayStart = dayStart;
this.dayEnd = dayEnd;
}
public void setNextHandler(handler handler){
nextHandler = handler;
}
protected abstract void handlerLeave(LeaveRequest leaveRequest);
public final void submit(LeaveRequest leaveRequest){
if (this.nextHandler != null && leaveRequest.getDay() > this.dayEnd){
this.nextHandler.submit(leaveRequest);
}else {
this.handlerLeave(leaveRequest);
System.out.println("流程结束");
}
}
}
class GroupLeader extends handler{
public GroupLeader() {
super(0,DAY_ONE);
}
@Override
protected void handlerLeave(LeaveRequest leaveRequest) {
System.out.println("小组长批准了");
}
}
class Manager extends handler{
public Manager() {
super(DAY_ONE,DAY_THREE);
}
@Override
protected void handlerLeave(LeaveRequest leaveRequest) {
System.out.println("部门经理批准了");
}
}
class GeneralManager extends handler{
public GeneralManager() {
super(DAY_THREE,DAY_SEVEN);
}
@Override
protected void handlerLeave(LeaveRequest leaveRequest) {
System.out.println("总经理批准了");
}
}
状态模式
定义
对有状态的对象,把复杂的“逻辑判断”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
结构
- 环境角色:也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理
- 抽象状态角色:定义一个接口,用以封装环境对象中的特定状态对应的行为
- 具体状态角色:实现抽象状态所对应的行为
举个栗子
/*
电梯接下来能进行的操作取决于它当前的状态,例如电梯在运行时,不能开门等。
简单来写,就会出现大量的if-esle,来判断是否能执行该操作。
当然,下面的状态模式依旧不能很好支持 ‘开闭原则’
*/
/**
* @author strind
* @version 1.0
* @description 状态模式
* @date 2024/2/7 10:27
*/
public class test {
public static void main(String[] args) {
Context context = new Context();
context.setLiftState(Context.CLOSING_STATE);
context.close();
context.open();
context.run();
context.stop();
}
}
// 抽象状态角色
abstract class LiftState{
// 环境对象
protected Context context;
public void setContext(Context context) {
this.context = context;
}
abstract void open();
abstract void close();
abstract void run();
abstract void stop();
}
// 环境角色
class Context{
public static final OpeningState OPENING_STATE = new OpeningState();
public static final ClosingState CLOSING_STATE = new ClosingState();
public static final RunningState RUNNING_STATE = new RunningState();
public static final StopState STOP_STATE = new StopState();
private LiftState liftState;
public LiftState getLiftState() {
return liftState;
}
public void setLiftState(LiftState liftState) {
this.liftState = liftState;
this.liftState.setContext(this);
}
public void open(){
this.liftState.open();
}
public void close(){
this.liftState.close();
}
public void run(){
this.liftState.run();
}
public void stop(){
this.liftState.stop();
}
}
// 开启状态类
class OpeningState extends LiftState{
@Override
void open() {
System.out.println("电梯打开。。。");
}
@Override
void close() {
super.context.setLiftState(Context.CLOSING_STATE);
super.context.close();
}
@Override
void run() { }
@Override
void stop() { }
}
// 关闭状态类
class ClosingState extends LiftState{
@Override
void open() {
super.context.setLiftState(Context.OPENING_STATE);
super.context.open();
}
@Override
void close() {
System.out.println("电梯门关闭。。");
}
@Override
void run() {
super.context.setLiftState(Context.RUNNING_STATE);
super.context.run();
}
@Override
void stop() {
super.context.setLiftState(Context.STOP_STATE);
super.context.stop();
}
}
// 运行状态类
class RunningState extends LiftState{
@Override
void open() {
}
@Override
void close() {
}
@Override
void run() {
System.out.println("正在运行。。");
}
@Override
void stop() {
super.context.setLiftState(Context.STOP_STATE);
super.context.stop();
}
}
// 停止状态类
class StopState extends LiftState{
@Override
void open() {
super.context.setLiftState(Context.OPENING_STATE);
super.context.open();
}
@Override
void close() {
super.context.setLiftState(Context.CLOSING_STATE);
super.context.close();
}
@Override
void run() {
super.context.setLiftState(Context.RUNNING_STATE);
super.context.run();
}
@Override
void stop() {
System.out.println("已停止。。");
}
}
使用场景
- 当一个对象的行为取决于它的状态,并且他必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式
- 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时
观察者模式
定义
又称为发布-订阅模式,定义一种一对多的依赖关系,让多个观察者对象同时监听一个主题对象,主题对象在状态改变时,通知所有的观察者对象,使他们能够自动更新自己
结构
- 抽象主题角色:把所有的观察者对象保存在集合里,每个主题都可以有任意数量的观察者,它提供一个接口,进行观察者的增减
- 具体主题角色:将有关状态存入具体观察者对象,在具体主题的内部状态发送改变时,给所有注册的观察者发送通知
- 抽象观察者:是观察者的抽象类,定义更新接口,使得在得到主题变更时更新自己
- 具体观察者:实现抽象观察者的更新接口,以便主题变更时更新自己。
举个栗子
/**
微信公众号更新后,会通知相关订阅了该公众号的用户
*/
/**
* @author strind
* @version 1.0
* @description 观察者模式
* @date 2024/2/7 11:04
*/
public class test {
public static void main(String[] args) {
Subject subject = new SubjectImpl();
subject.attach(new WeChatObserver("张三"));
subject.attach(new WeChatObserver("李四"));
subject.attach(new WeChatObserver("王五"));
subject.attach(new WeChatObserver("赵六"));
subject.notify("更新文章内容");
}
}
// 抽象主题
interface Subject{
void attach(Observer observer);
void detach(Observer observer);
void notify(String msg);
}
// 具体主题
class SubjectImpl implements Subject{
private List<Observer> observerList = new ArrayList<>();
@Override
public void attach(Observer observer) {
observerList.add(observer);
}
@Override
public void detach(Observer observer) {
observerList.remove(observer);
}
@Override
public void notify(String msg) {
for (Observer observer : observerList) {
observer.update(msg);
}
}
}
// 抽象观察者
interface Observer{
void update(String msg);
}
// 具体观察者
class WeChatObserver implements Observer{
private String name;
public WeChatObserver(String name) {
this.name = name;
}
@Override
public void update(String msg) {
System.out.println(name + "--" + msg);
}
}
中介模式
定义
又叫调停模式,定义一个中介角色来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以单独地改变它们之间的交互。
结构
- 抽象中介角色:是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
- 具体中介者角色:实现中介者接口,定义一个List 来管理同事对象,协调各个同事角色之间的交互关系,因此他依赖于同事角色
- 抽象同事类角色:定义同事类接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能
- 具体同事类角色:是抽象同事类的实现者,当需要与其他同事对象交互时,有中介者对象负责后续的交互
举个栗子
/**
* @author strind
* @version 1.0
* @description 中介者模式 实现租房
* @date 2024/2/11 10:40
*/
public class test {
public static void main(String[] args) {
MediatorStructure mediator = new MediatorStructure();
Tenant tenant = new Tenant("Tom", mediator);
HouseOwner owner = new HouseOwner("Owner", mediator);
mediator.setTenant(tenant);
mediator.setHouseOwner(owner);
tenant.contact("我要租一间房");
owner.contact("没有合适的房子");
}
}
// 抽象同事类
abstract class Person{
protected String name;
protected Mediator mediator;
public Person(String name, Mediator mediator) {
this.name = name;
this.mediator = mediator;
}
}
// 抽象中介者
abstract class Mediator{
abstract void contact(String message, Person person);
}
// 具体同事类
class Tenant extends Person{
public Tenant(String name, Mediator mediator) {
super(name, mediator);
}
// 和中介联系
public void contact(String message){
mediator.contact(message,this);
}
public void getMessage(String message){
System.out.println("租房者 " + name + "获取到信息:" + message);
}
}
// 具体同事类
class HouseOwner extends Person{
public HouseOwner(String name, Mediator mediator) {
super(name, mediator);
}
// 和中介联系
public void contact(String message){
mediator.contact(message,this);
}
// 获取信息
public void getMessage(String message){
System.out.println("房主 " + name + "获取到信息:" + message);
}
}
// 具体的中介者
class MediatorStructure extends Mediator{
// 聚合房主和租房者
private HouseOwner houseOwner;
private Tenant tenant;
public HouseOwner getHouseOwner() {
return houseOwner;
}
public void setHouseOwner(HouseOwner houseOwner) {
this.houseOwner = houseOwner;
}
public Tenant getTenant() {
return tenant;
}
public void setTenant(Tenant tenant) {
this.tenant = tenant;
}
@Override
void contact(String message, Person person) {
if (person == houseOwner) {
tenant.getMessage(message);
}else {
houseOwner.getMessage(message);
}
}
}
缺点:
当同事类太多时,中介者的 职责将很大,他会变得庞大而复杂,以至于难以维护。
使用场景:
- 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。
- 当想创建一个运行于多个类之间的对象,又不想生成新的子类
迭代器模式
定义
提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚会对象的内部表示
结构
- 抽象聚合角色:定义存储,添加,删除聚合元素以及创建迭代器对象的接口
- 具体聚合角色:实现抽象聚合类,返回一个具体迭代器的实例
- 抽象迭代器角色:定义访问和遍历聚合元素的接口,通常包含 hasNext( )、next( ) 等方法
- 具体迭代器角色:实现抽象迭代器接口中定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
举个栗子
/**
* @author strind
* @version 1.0
* @description 迭代器模式
* @date 2024/2/11 11:07
*/
public class test {
public static void main(String[] args) {
StudentAggregateImpl aggregate = new StudentAggregateImpl();
aggregate.addStudent(new Student("Jarry","4"));
aggregate.addStudent(new Student("Toms","2"));
aggregate.addStudent(new Student("Ming","5"));
SIterator iterator = aggregate.getSIterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
class Student{
private String name;
private String number;
public Student(String name, String number) {
this.name = name;
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", number='" + number + '\'' +
'}';
}
}
// 抽象迭代器接口
interface SIterator{
boolean hasNext();
Student next();
}
// 具体迭代器
class SIteratorImpl implements SIterator{
private List<Student> list;
public SIteratorImpl(List<Student> list) {
this.list = list;
}
private int position = 0;
@Override
public boolean hasNext() {
return position < list.size();
}
@Override
public Student next() {
return list.get(position ++);
}
}
// 抽象聚合类
interface StudentAggregate{
void addStudent(Student student);
void removeStudent(Student student);
// 获取迭代器对象
SIterator getSIterator();
}
class StudentAggregateImpl implements StudentAggregate{
private List<Student> list = new ArrayList<>();
@Override
public void addStudent(Student student) {
list.add(student);
}
@Override
public void removeStudent(Student student) {
list.remove(student);
}
@Override
public SIterator getSIterator() {
return new SIteratorImpl(list);
}
}
在使用中,只要让我们自己定义的容器类实现 Java.util.Iterable 并实现其中的iterator( )方法使其返回一个 java.util.Iterator 的实现类就可以了。
访问者模式
定义
封装一些作用于某种数据结构中的各元素的操作,它可能在不改变这个数据结构的前提下定义作用于这些元素的新的操作
结构
- 抽象访问者角色:定义了对每一个元素访问的行为,它的参数就是可以访问的元素,它的方法个数理论上与元素个数相等。(访问者模式要求元素类的个数不能改变)
- 具体访问者角色:对每个元素类访问时所产生的具体行为。
- 抽象元素角色:定义一个接受访问者的方法,其意义是指,每一个元素都要可以被访问者访问
- 具体元素角色:提供接受访问的具体实现,而这个具体的实现,通常情况下是使用访问者的访问元素的方法
- 对象结构角色:定义当中所提到的对象结构,对象结构是一个抽象表述,具体点可以理解为一个具有容器性质或者复合对象特性的类,它会含有一组元素,并且可以迭代这些元素,共访问者访问。
举个栗子
/**
* @author strind
* @version 1.0
* @description 访问者模式 喂宠物
* @date 2024/2/11 11:36
*/
public class test {
public static void main(String[] args) {
Home home = new Home();
home.add(new Dog());
home.add(new Cat());
home.action(new Owner());
System.out.println("=====================");
home.action(new Owner());
}
}
// 抽象元素
interface Animal{
void accept(Person person);
}
// 具体元素
class Cat implements Animal{
@Override
public void accept(Person person) {
person.feed(this);
System.out.println("cat......");
}
}
class Dog implements Animal{
@Override
public void accept(Person person) {
person.feed(this);
System.out.println("dog.......");
}
}
// 抽象访问者角色
interface Person{
void feed(Cat cat);
void feed(Dog dog);
}
// 具体访问者
class Owner implements Person{
@Override
public void feed(Cat cat) {
System.out.println("Owner feed his cat");
}
@Override
public void feed(Dog dog) {
System.out.println("Owner feed his dog");
}
}
class Other implements Person{
@Override
public void feed(Cat cat) {
System.out.println("Other feed this cat");
}
@Override
public void feed(Dog dog) {
System.out.println("Other feed this dog");
}
}
// 对象结构类
class Home{
private List<Animal> list = new ArrayList<>();
public void add(Animal animal){
list.add(animal);
}
public void action(Person person){
for (Animal animal : list) {
animal.accept(person);
}
}
}
备忘录模式
定义
有叫快照模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到之前的状态。
结构
- 发起人:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录的功能,实现其他业务功能,他可以访问备忘录里的所有信息。
- 备忘录:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
- 管理者:对备忘录进行管理,提供保存与获取备忘录的功能,但不能对备忘录的内容进行访问与修改。
备忘录的两个等效接口:
- 窄接口:管理者(和其他发起人对象之外的任何对象)看到的是备忘录的窄接口,这个窄接口只允许它把备忘录传给其他对象
- 宽接口:发起人对象可以看到一个宽接口,这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态。
举个栗子
/**
* @author strind
* @version 1.0
* @description 备忘录模式(白箱) 打怪
* @date 2024/2/12 10:16
*/
public class test {
public static void main(String[] args) {
System.out.println("-----------before------------");
GameRole gameRole = new GameRole();
gameRole.initState();
gameRole.play();
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
roleStateCaretaker.setRoleStateMemento(gameRole.saveState());
System.out.println("-----------after------------");
gameRole.fight();
gameRole.play();
System.out.println("-----------recover------------");
gameRole.recoverState(roleStateCaretaker.getRoleStateMemento());
gameRole.play();
}
}
// 备忘录角色
class RoleStateMemento{
private int vit; // 血条
private int atk; // 攻击
private int def; //防御
public RoleStateMemento(int vit, int atk, int def) {
this.vit = vit;
this.atk = atk;
this.def = def;
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
// 发起人
class GameRole{
private int vit; // 血条
private int atk; // 攻击
private int def; //防御
public void initState(){
this.vit = 100;
this.atk = 100;
this.def = 100;
}
public void fight(){
this.vit = 0;
this.atk = 0;
this.def = 0;
}
// 保存状态
public RoleStateMemento saveState(){
return new RoleStateMemento(vit,atk,def);
}
public void play(){
System.out.println("角色生命力" + vit);
System.out.println("角色攻击力" + atk);
System.out.println("角色防御力" + def);
}
// 恢复状态
public void recoverState(RoleStateMemento roleStateMemento){
this.vit = roleStateMemento.getVit();
this.atk = roleStateMemento.getAtk();
this.def = roleStateMemento.getDef();
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
// 管理者
class RoleStateCaretaker{
private RoleStateMemento roleStateMemento;
public RoleStateMemento getRoleStateMemento() {
return roleStateMemento;
}
public void setRoleStateMemento(RoleStateMemento roleStateMemento) {
this.roleStateMemento = roleStateMemento;
}
}
/**
* @author strind
* @version 1.0
* @description 备忘录模式(黑箱) 打怪
* @date 2024/2/12 10:16
*/
public class test {
public static void main(String[] args) {
System.out.println("-----------before------------");
GameRole gameRole = new GameRole();
gameRole.initState();
gameRole.play();
RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
roleStateCaretaker.setMemento(gameRole.saveState());
System.out.println("-----------after------------");
gameRole.fight();
gameRole.play();
System.out.println("-----------recover------------");
gameRole.recoverState(roleStateCaretaker.getMemento());
gameRole.play();
}
}
// 备忘录接口,对外提供窄接口
interface Memento{
}
// 发起人
class GameRole{
private int vit; // 血条
private int atk; // 攻击
private int def; //防御
public void initState(){
this.vit = 100;
this.atk = 100;
this.def = 100;
}
public void fight(){
this.vit = 0;
this.atk = 0;
this.def = 0;
}
private class RoleStateMemento implements Memento{
private int vit; // 血条
private int atk; // 攻击
private int def; //防御
public RoleStateMemento(int vit, int atk, int def) {
this.vit = vit;
this.atk = atk;
this.def = def;
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
// 保存状态
public Memento saveState(){
return new RoleStateMemento(vit,atk,def);
}
public void play(){
System.out.println("角色生命力" + vit);
System.out.println("角色攻击力" + atk);
System.out.println("角色防御力" + def);
}
// 恢复状态
public void recoverState(Memento memento){
RoleStateMemento roleStateMemento = (RoleStateMemento) memento;
this.vit = roleStateMemento.getVit();
this.atk = roleStateMemento.getAtk();
this.def = roleStateMemento.getDef();
}
public int getVit() {
return vit;
}
public void setVit(int vit) {
this.vit = vit;
}
public int getAtk() {
return atk;
}
public void setAtk(int atk) {
this.atk = atk;
}
public int getDef() {
return def;
}
public void setDef(int def) {
this.def = def;
}
}
// 管理者
class RoleStateCaretaker {
private Memento Memento;
public pattern.memento.Memento getMemento() {
return Memento;
}
public void setMemento(pattern.memento.Memento memento) {
Memento = memento;
}
}
在黑箱里,管理者是无法访问备忘录的;
在备忘录模式中,实现双重接口的方法,就是将备忘录设计成发起人的内部类
解释器模式
定义
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
结构
- 抽象表达式:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret( )。
- 终结符表达式:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体的中街表达式与之相对应。
- 非终结符表达式:抽象表达式的子类,用来实现文法中与非终结者相关的操作,文法中否定每条规则都对应一个非终结者符表达式
- 环境角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
- 客户端:主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。
举个栗子
/**
* @author strind
* @version 1.0
* @description 解释器模式 实现加减法计算
* @date 2024/2/12 10:57
*/
public class test {
public static void main(String[] args) {
Context context = new Context();
Variable a = new Variable("a");
Variable b = new Variable("b");
Variable c = new Variable("c");
Variable d = new Variable("d");
context.assign(a,1);
context.assign(b,5);
context.assign(c,8);
context.assign(d,9);
AbstractExpression expression = new Minus(a,new Plus(new Minus(b,c),d));
int result = expression.interpret(context);
System.out.println(expression + "=" + result);
}
}
// 环境类
class Context{
private Map<Variable,Integer> map = new HashMap<>();
public void assign(Variable var, Integer value){
map.put(var,value);
}
//
public int gatValue(Variable var){
return map.get(var);
}
}
// 抽象表达式
abstract class AbstractExpression{
// 文法表达式
public abstract int interpret(Context context);
}
// 终结符表达式
class Variable extends AbstractExpression{
private String name;
public Variable(String name) {
this.name = name;
}
@Override
public int interpret(Context context) {
return context.gatValue(this);
}
@Override
public String toString() {
return name;
}
}
// 加法表达式(非终结符表达式)
class Plus extends AbstractExpression{
private AbstractExpression left;
private AbstractExpression right;
public Plus(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) + right.interpret(context);
}
@Override
public String toString() {
return "("+ left.toString() + " + " + right.toString() + ")";
}
}
// 减法表达式
class Minus extends AbstractExpression{
private AbstractExpression left;
private AbstractExpression right;
public Minus(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) - right.interpret(context);
}
@Override
public String toString() {
return "("+ left.toString() + " - " + right.toString() + ")";
}
}
終わり