本文是学习设计模式时做的笔记,原视频链接:
https://www.bilibili.com/video/BV1G4411c7N4
目录
责任链模式(Chain of Responsibility)
模板方法模式(Template Method)
模板方法模式:一个抽象类公开定义“执行它的方法”的模板,将模板中的一些步骤延迟到子类实现。
使用场景
要完成一项繁琐但步骤固定的工作。
实现方式
化妆的步骤:清洁面部,上隔离霜,抹粉底液,涂遮瑕膏,刷散粉,画眉毛,画眼影,修容,打高光,涂口红。我们认为这个步骤比较固定。
1.会化妆的女孩(Girl)
public abstract class Girl {
abstract void clean(); //清洁面部
abstract void make_up_base(); //上隔离霜
abstract void foundation(); //抹粉底液
abstract void concealer(); //涂遮瑕膏
abstract void loosePowder(); //刷散粉
abstract void eyebrowPencil(); //画眉毛
abstract void eyeShadow(); //画眼影
abstract void contour(); //修容
abstract void highlight(); //打高光
abstract void lipstick(); //涂口红
public final void makeUp() { //化妆
clean();
make_up_base();
foundation();
concealer();
loosePowder();
eyebrowPencil();
eyeShadow();
contour();
highlight();
lipstick();
}
}
2.一些很会化妆的女孩,我们称之为美人(Beauty)
public class Beauty extends Girl {
@Override
public void clean() {
System.out.println("面部干净啊");
}
@Override
public void make_up_base() {
System.out.println("隔离霜上的好啊");
}
@Override
public void foundation() {
System.out.println("粉底液抹的好啊");
}
@Override
public void concealer() {
System.out.println("遮瑕膏涂的好啊");
}
@Override
public void loosePowder() {
System.out.println("散粉刷的好啊");
}
@Override
public void eyebrowPencil() {
System.out.println("眉毛画的好啊");
}
@Override
public void eyeShadow() {
System.out.println("眼影画的好啊");
}
@Override
public void contour() {
System.out.println("修容修的好啊");
}
@Override
void highlight() {
System.out.println("高光打的好啊");
}
@Override
public void lipstick() {
System.out.println("口红涂的好啊");
}
}
3.吃瓜群众(Client)
public class Client {
public static void main(String[] args) {
Girl beauty = new Beauty();
beauty.makeUp();
}
}
输出结果:
面部干净啊
隔离霜上的好啊
粉底液抹的好啊
遮瑕膏涂的好啊
散粉刷的好啊
眉毛画的好啊
眼影画的好啊
修容修的好啊
高光打的好啊
口红涂的好啊
命令模式(Command)
命令模式:将一个请求封装为一个对象,以便使用不同参数来表示不同的请求。命令模式使得请求发送者与请求接收者消除彼此之间的耦合。
使用场景
虎符是古代皇帝调兵遣将用的兵符,持符者即获得调兵遣将权。
持符的将军(General)只需要发布军令(Command),不用管军令的执行者是谁;士兵(Soldier)只需要听从军令,不用管军令的发布者是谁。
实现方式
1.创建一个命令接口Command
public interface Command {
void execute();
}
2.创建命令接收者Soldier
public class Soldier {
public void launch1() {
System.out.println("士兵前进一公里");
}
public void launch10() {
System.out.println("士兵前进十公里");
}
public void launch100() {
System.out.println("士兵前进一百公里");
}
public void retreat1() {
System.out.println("士兵后退一公里");
}
public void retreat10() {
System.out.println("士兵后退十公里");
}
public void retreat100() {
System.out.println("士兵后退一百公里");
}
}
3.创建实现了Command接口的实体类
public class LaunchCommand implements Command {
Soldier soldier;
int commandType;
public LaunchCommand(Soldier soldier, int commandType) {
this.soldier = soldier;
this.commandType = commandType;
}
@Override
public void execute() {
switch (commandType) {
case 1:
soldier.launch1();
break;
case 2:
soldier.launch10();
break;
case 3:
soldier.launch100();
break;
case -1:
soldier.retreat1();
break;
case -2:
soldier.retreat10();
break;
case -3:
soldier.retreat100();
break;
}
}
}
//该类用来初始化命令对象
public class NoCommand implements Command {
@Override
public void execute() {
System.out.println("空命令");
}
}
4.创建命令调用类General
public class General {
Command[] commands;
public General(int countCommands) {
commands = new Command[countCommands];
int i;
for (i = 0; i < countCommands; i++) {
commands[i] = new NoCommand();
}
}
public void setCommand(int commandNumber, Command command) {
commands[commandNumber] = command;
}
public void issueCommand() {
for (Command command : commands) {
command.execute();
}
}
}
5.吃瓜群众Client
public class Client {
public static void main(String[] args) {
Soldier soldier = new Soldier();
General general = new General(7);
general.setCommand(0, new LaunchCommand(soldier, 1));
general.setCommand(1, new LaunchCommand(soldier, 2));
general.setCommand(2, new LaunchCommand(soldier, 3));
general.setCommand(4, new LaunchCommand(soldier, -1));
general.setCommand(5, new LaunchCommand(soldier, -2));
general.setCommand(6, new LaunchCommand(soldier, -3));
general.issueCommand();
}
}
输出结果:
士兵前进一公里
士兵前进十公里
士兵前进一百公里
空命令
士兵后退一公里
士兵后退十公里
士兵后退一百公里
访问者模式(Visitor)
访问者模式:封装一些作用于某种数据结构的各元素的操作,在不改变数据结构的前提下定义作用于这些元素的新的操作。
将数据结构与数据操作分离,主要解决数据结构和操作的耦合性问题。
使用场景
需要对一个对象结构中的对象进行很多不同的操作(这些操作彼此没有关联),同时需要避免让这些操作污染这些对象的类。
实现方式
墨家的前任巨子推荐小孩子天明(Tianming)做墨家新的巨子。
墨家的六位头领盗跖(Zhi)、徐夫子(Xu)、大铁锤(Chui)、雪女(Xue)、班大师(Ban)、高渐离(Gao)对此事进行了投票表决:
盗跖、雪女、高渐离投了赞成票(For),徐夫子、大铁锤、班大师投了反对票(Against)。
1.创建抽象类墨家头领(MohismLeader)
public abstract class MohismLeader {
public abstract void accept(Visitor visitor);
}
这里还没有创建Visitor,所以暂时会报错。
2.创建墨家的六位头领,继承MohismLeader
public class Zhi extends MohismLeader {
@Override
public void accept(Visitor visitor) {
visitor.getZhiResult(this);
}
}
public class Xu extends MohismLeader {
@Override
public void accept(Visitor visitor) {
visitor.getXuResult(this);
}
}
public class Chui extends MohismLeader {
@Override
public void accept(Visitor visitor) {
visitor.getChuiResult(this);
}
}
public class Xue extends MohismLeader {
@Override
public void accept(Visitor visitor) {
visitor.getXueResult(this);
}
}
public class Ban extends MohismLeader {
@Override
public void accept(Visitor visitor) {
visitor.getBanResult(this);
}
}
public class Gao extends MohismLeader {
@Override
public void accept(Visitor visitor) {
visitor.getGaoResult(this);
}
}
3.定义一个表示访问者的接口Visitor
public interface Visitor {
void getZhiResult(Zhi zhi);//盗跖的意见
void getXuResult(Xu xu);//徐夫子的意见
void getChuiResult(Chui chui);//大铁锤的意见
void getXueResult(Xue xue);//雪女的意见
void getBanResult(Ban ban);//班大师的意见
void getGaoResult(Gao gao);//高渐离的意见
}
4.创建实现了Visitor接口的实体类
public class For implements Visitor {
@Override
public void getZhiResult(Zhi zhi) {
System.out.println("盗跖赞成");
}
@Override
public void getXuResult(Xu xu) {
System.out.println("徐夫子赞成");
}
@Override
public void getChuiResult(Chui chui) {
System.out.println("大铁锤赞成");
}
@Override
public void getXueResult(Xue xue) {
System.out.println("雪女赞成");
}
@Override
public void getBanResult(Ban ban) {
System.out.println("班大师赞成");
}
@Override
public void getGaoResult(Gao gao) {
System.out.println("高渐离赞成");
}
}
public class Against implements Visitor {
@Override
public void getZhiResult(Zhi zhi) {
System.out.println("盗跖反对");
}
@Override
public void getXuResult(Xu xu) {
System.out.println("徐夫子反对");
}
@Override
public void getChuiResult(Chui chui) {
System.out.println("大铁锤反对");
}
@Override
public void getXueResult(Xue xue) {
System.out.println("雪女反对");
}
@Override
public void getBanResult(Ban ban) {
System.out.println("班大师反对");
}
@Override
public void getGaoResult(Gao gao) {
System.out.println("高渐离反对");
}
}
5.创建对象结构类ObjectStructure
ObjectStructure类的对象是赞成票或者反对票的容器。
import java.util.LinkedList;
import java.util.List;
public class ObjectStructure {
private List<MohismLeader> leaders = new LinkedList<>();
public void add(MohismLeader leader) {
leaders.add(leader);
}
public void remove(MohismLeader leader) {
leaders.remove(leader);
}
public void display(Visitor visitor) {
for (MohismLeader leader : leaders) {
leader.accept(visitor);
}
}
}
6.吃瓜天明Tianming
public class Tianming {
public static void main(String[] args) {
ObjectStructure objectStructure1 = new ObjectStructure();
ObjectStructure objectStructure2 = new ObjectStructure();
objectStructure1.add(new Zhi());
objectStructure2.add(new Xu());
objectStructure2.add(new Chui());
objectStructure1.add(new Xue());
objectStructure2.add(new Ban());
objectStructure1.add(new Gao());
For _for = new For();
Against against = new Against();
objectStructure1.display(_for);
objectStructure2.display(against);
}
}
输出结果:
盗跖赞成
雪女赞成
高渐离赞成
徐夫子反对
大铁锤反对
班大师反对
迭代器模式(Iterator)
迭代器模式:用于顺序访问集合对象元素,不需要知道集合对象的底层表示。
使用场景
遍历集合对象。
实现方式
一所大学可能设有多个学院(College),每个学院可能设有多个系(Department)。
郑州大学设有机械工程学院(Mechanical)和外语学院(Languages)。
机械工程学院设有机械工程和工业设计两个系。
外语学院设有英语、日语、俄语、德语四个系。
使用迭代器模式可以对郑州大学的院系进行遍历。
1.创建接口College
import java.util.Iterator;
public interface College {
Iterator getIterator();//获得迭代器
String getName();//获得学院名称
String getDescribe();//获得学院描述
void addDepartment(String name, String describe);//添加系
}
创建系类Department
public class Department {
private String name;
private String describe;
public Department(String name, String describe) {
this.name = name;
this.describe = describe;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
}
2.创建机械工程学院Mechanical和外语学院Languages
机械工程学院使用数组,外语学院使用List集合。
import java.util.Iterator;
public class Mechanical implements College {
Department[] departments;
int index = 0;
public Mechanical() {
departments = new Department[2];
addDepartment("机械工程", "百分之八十的人数,百分之二十的女生");
addDepartment("工业设计", "百分之二十的人数,百分之八十的女生");
}
@Override
public void addDepartment(String name, String describe) {
Department department = new Department(name, describe);
departments[index] = department;
index++;
}
@Override
public Iterator getIterator() {
return new MechanicalIterator(departments);
}
@Override
public String getName() {
return "机械工程学院";
}
@Override
public String getDescribe() {
return "盛产帅哥";
}
private class MechanicalIterator implements Iterator {
Department[] departments;
int i = 0;
public MechanicalIterator(Department[] departments) {
this.departments = departments;
}
@Override
public boolean hasNext() {
if (i < departments.length) {
return true;
} else {
return false;
}
}
@Override
public Object next() {
if (this.hasNext()) {
return departments[i++];
}
return null;
}
}
}
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
public class Languages implements College {
List<Department> departmentList;
public Languages() {
departmentList = new ArrayList<Department>();
addDepartment("英语", "Hello");
addDepartment("日语", "こんにちは");
addDepartment("俄语", "Здравствыйте");
addDepartment("德语", "Hallo!");
}
@Override
public void addDepartment(String name, String describe) {
Department department = new Department(name, describe);
departmentList.add(department);
}
@Override
public Iterator getIterator() {
return new LanguagesIterator();
}
@Override
public String getName() {
return "外语学院";
}
@Override
public String getDescribe() {
return "盛产美女";
}
private class LanguagesIterator implements Iterator {
int i = 0;
@Override
public boolean hasNext() {
if (i < departmentList.size()) {
return true;
} else {
return false;
}
}
@Override
public Object next() {
return departmentList.get(i++);
}
}
}
3.创建输出工具类Output
import java.util.Iterator;
import java.util.List;
public class Output {
List<College> collegeList;
public Output(List<College> collegeList) {
this.collegeList = collegeList;
}
public void printCollege() {
Iterator<College> iterator = collegeList.iterator();
while (iterator.hasNext()) {
College college = (College) iterator.next();
System.out.println("----" + college.getName() + ": " + college.getDescribe());
printDepartment(college.getIterator());
}
}
public void printDepartment(Iterator iterator) {
while (iterator.hasNext()) {
Department department = (Department) iterator.next();
System.out.println(department.getName() + ": " + department.getDescribe());
}
}
}
4.吃瓜群众Client
import java.util.ArrayList;
import java.util.List;
public class Client {
public static void main(String[] args) {
List<College> collegeList = new ArrayList<College>();
Mechanical mechanicalCollege = new Mechanical();
Languages languagesCollege = new Languages();
collegeList.add(mechanicalCollege);
collegeList.add(languagesCollege);
Output output = new Output(collegeList);
output.printCollege();
}
}
输出结果:
----机械工程学院: 盛产帅哥
机械工程: 百分之八十的人数,百分之二十的女生
工业设计: 百分之二十的人数,百分之八十的女生
----外语学院: 盛产美女
英语: Hello
日语: こんにちは
俄语: Здравствыйте
德语: Hallo!
观察者模式(Observer)
观察者模式:当一个对象被修改时,则会自动通知依赖它的对象。
使用场景
对象间存在一对多关系。
实现方式
某公司有四名员工:
程序员李明,程序员自豪,产品经理韩梅梅,产品经理明凯。
领导通知李明、自豪、明凯明天放假;
通知李明、韩梅梅今晚加班。
1.创建消息发布者接口Subject,消息接收者接口Observer
public interface Subject {
void register(Observer observer);//登记消息接收者
void remove(Observer observer);//移除消息接收者
void release(String announcement);//发布公告
}
public interface Observer {
void receive(String announcement);//接收公告
}
2.创建消息发送者Leader
import java.util.ArrayList;
import java.util.List;
public class Leader implements Subject {
private String announcement;//公告内容
private List<Observer> observers;//消息接收者
public Leader() {
observers = new ArrayList<Observer>();
}
public String getAnnouncement() {
return announcement;
}
public void setAnnouncement(String announcement) {
this.announcement = announcement;
}
@Override
public void register(Observer observer) {
observers.add(observer);
}
@Override
public void remove(Observer observer) {
observers.remove(observer);
}
@Override
public void release(String announcement) {
setAnnouncement(announcement);
for (int i = 0; i < observers.size(); i++) {
observers.get(i).receive(getAnnouncement());
}
}
}
3.创建消息接收者Programmer(程序员)和ProductManager(产品经理)
public class Programmer implements Observer {
private String name;
public Programmer(String name) {
this.name = name;
}
@Override
public void receive(String announcement) {
System.out.println("程序员" + name + "收到消息:" + announcement);
}
}
public class ProductManager implements Observer {
private String name;
public ProductManager(String name) {
this.name = name;
}
@Override
public void receive(String announcement) {
System.out.println("产品经理" + name + "收到消息:" + announcement);
}
}
4.吃瓜群众Client
public class Client {
public static void main(String[] args) {
Observer ming = new Programmer("李明");
Observer mei = new ProductManager("韩梅梅");
Observer uzi = new Programmer("自豪");
Observer clearlove = new ProductManager("明凯");
Subject leader = new Leader();
leader.register(ming);
leader.register(uzi);
leader.register(clearlove);
leader.release("明天放假!");
System.out.println("--------");
leader.register(mei);
leader.remove(uzi);
leader.remove(clearlove);
leader.release("今晚加班");
}
}
输出结果:
程序员李明收到消息:明天放假!
程序员自豪收到消息:明天放假!
产品经理明凯收到消息:明天放假!
--------
程序员李明收到消息:今晚加班
产品经理韩梅梅收到消息:今晚加班
中介者模式(Mediator)
中介者模式:提供一个中介类,该类处理不同类之间的通信,并支持松耦合,使代码易于维护。
使用场景
降低多个对象和类之间的通信复杂性。
实现方式
在一个QQ群中,每个群员都将消息发送到群聊中,每两个群员之间不进行直接通信。
1.创建群聊GroupChat
import java.util.Date;
public class GroupChat {
public static void showMessage(User user, String message) {
System.out.println(new Date().toString());
System.out.println(user.getName() + ":" + message);
}
}
这里还没有创建User,所以暂时会报错。
2.创建群成员User
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void sendMessage(String message) {
GroupChat.showMessage(this, message);
}
}
3.吃瓜群众Client
public class Client {
public static void main(String[] args) {
User liubei = new User("刘备");
User guanyu = new User("关羽");
User zhangfei = new User("张飞");
guanyu.sendMessage("关羽虽一介武夫,亦颇知忠义二字。");
guanyu.sendMessage("正所谓择木之禽,得栖良木,择主之臣,得遇明主,关某平生之愿足矣。");
guanyu.sendMessage("从今往后,关某之命即是刘兄之命,关某之躯即是刘兄之躯,但凭驱使,绝无二心。");
zhangfei.sendMessage("俺也一样!");
guanyu.sendMessage("某誓与兄患难与共,终生相伴,生死相随。");
zhangfei.sendMessage("俺也一样!");
guanyu.sendMessage("有渝此言,天人共戮之。");
zhangfei.sendMessage("俺也一样!");
}
}
输出结果:
Fri Jan 22 18:11:09 CST 2021
关羽:关羽虽一介武夫,亦颇知忠义二字。
Fri Jan 22 18:11:09 CST 2021
关羽:正所谓择木之禽,得栖良木,择主之臣,得遇明主,关某平生之愿足矣。
Fri Jan 22 18:11:09 CST 2021
关羽:从今往后,关某之命即是刘兄之命,关某之躯即是刘兄之躯,但凭驱使,绝无二心。
Fri Jan 22 18:11:09 CST 2021
张飞:俺也一样!
Fri Jan 22 18:11:09 CST 2021
关羽:某誓与兄患难与共,终生相伴,生死相随。
Fri Jan 22 18:11:09 CST 2021
张飞:俺也一样!
Fri Jan 22 18:11:09 CST 2021
关羽:有渝此言,天人共戮之。
Fri Jan 22 18:11:09 CST 2021
张飞:俺也一样!
备忘录模式(Memento)
备忘录模式:保存一个对象的某个状态,以便在适当的时候恢复对象。
使用场景
在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
这样可以在以后将对象恢复到保存的状态。
实现方式
在某个过关小游戏中,玩家(CareTaker)操纵的角色(Originator)每到一个存档点都可以记录当前所在的位置(Place),角色阵亡后可以读取某个存档(Memento)继续游戏。
1.游戏地图中的位置类Place
public class Place {
private String placeName = "i wanna";
public Place(String placeName) {
this.placeName = placeName;
}
public String getPlaceName() {
return placeName;
}
public void setPlaceName(String placeName) {
this.placeName = placeName;
}
@Override
public String toString() {
return "Place{" +
"placeName='" + placeName + '\'' +
'}';
}
}
2.存档Memento,记录信息为当前所在位置
public class Memento {
private Place place;
public Memento(Place place) {
this.place = place;
}
public Place getPlace() {
return place;
}
}
3.玩家操纵的角色Originator
public class Originator {//Originator:发起人
private Place place;
public Place getPlace() {
return place;
}
public void setPlace(Place place) {
this.place = place;
}
public Memento savePlaceToMemento() {
System.out.println("存档成功");
return new Memento(place);
}
public void getPlaceFromMemento(Memento memento) {
place = memento.getPlace();
System.out.println("读档成功");
}
}
4.玩家CareTaker
import java.util.ArrayList;
import java.util.List;
public class CareTaker {//CareTaker:监护人
private List<Memento> mementoList = new ArrayList<Memento>();
public void add(Memento memento) {
mementoList.add(memento);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
5.客户端Client
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setPlace(new Place("大唐官府"));
originator.setPlace(new Place("化生寺"));
careTaker.add(originator.savePlaceToMemento());
originator.setPlace(new Place("方寸山"));
careTaker.add(originator.savePlaceToMemento());
originator.setPlace(new Place("女儿村"));
System.out.println("Current Place: " + originator.getPlace().toString());
originator.getPlaceFromMemento(careTaker.get(0));
System.out.println("First saved Place: " + originator.getPlace().toString());
originator.getPlaceFromMemento(careTaker.get(1));
System.out.println("Second saved Place: " + originator.getPlace().toString());
}
}
输出结果:
存档成功
存档成功
Current Place: Place{placeName='女儿村'}
读档成功
First saved Place: Place{placeName='化生寺'}
读档成功
Second saved Place: Place{placeName='方寸山'}
解释器模式(Interpreter)
解释器模式:提供评估语言的语法或表达式的方式。该模式实现了一个表达式接口,该接口解释一个特定的上下文。
在编译原理中,一个算术表达式通过词法分析器形成语法单元,而后这些词法单元再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树。这里的词法分析器和语法分析器都可以看做是解释器。
使用场景
对于一些固定文法构建一个解释句子的解释器。
实现方式
解释器模式包括四个部分:
Context:上下文,是一个环境角色,含有解释器之外的全局信息。
AbstractExpression:抽象表达式,声明一个抽象的解释方法interpret(),interpret()为抽象语法树中所有节点所共享。
TerminalExpression:终结符表达式,实现与文法中的终结符相关的解释操作。
NonTerminalExpression:非终结符表达式,实现与文法中的非终结符相关的解释操作。
不要在这个设计模式上死磕。
1.创建AbstractExpression:Expression
import java.util.HashMap;
public abstract class Expression {
//此处HashMap的key是表达式a\b\c,value是具体的值1\2\3
public abstract int interpret(HashMap<String, Integer> var);
}
2.创建TerminalExpression:VarExpression
import java.util.HashMap;
public class VarExpression extends Expression {
private String key;
public VarExpression(String key) {
this.key = key;
}
@Override
public int interpret(HashMap<String, Integer> var) {
return var.get(this.key);
}
}
3.创建NonTerminalExpression:SymbolExpression及其子类
import java.util.HashMap;
public class SymbolExpression extends Expression {
protected Expression left;
protected Expression right;
public SymbolExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override//默认实现
public int interpret(HashMap<String, Integer> var) {
return 0;
}
}
import java.util.HashMap;
public class AddExpression extends SymbolExpression {
public AddExpression(Expression left, Expression right) {
super(left, right);
}
public int interpret(HashMap<String, Integer> var) {
return super.left.interpret(var) + super.right.interpret(var);
}
}
import java.util.HashMap;
public class SubExpression extends SymbolExpression {
public SubExpression(Expression left, Expression right) {
super(left, right);
}
public int interpret(HashMap<String, Integer> var) {
return left.interpret(var) - right.interpret(var);
}
}
4.创建Context:Calculator
import java.util.HashMap;
import java.util.Stack;
public class Calculator {
private Expression expression;
public Calculator(String expStr) {//expStr: a + b
Stack<Expression> stack = new Stack<>();
char[] charArray = expStr.toCharArray();//charArray: [a, +, b]
Expression left = null;
Expression right = null;
for (int i = 0; i < charArray.length; i++) {
switch (charArray[i]) {
case '+':
left = stack.pop();
right = new VarExpression(String.valueOf(charArray[++i]));
stack.push(new AddExpression(left, right));
break;
case '-':
left = stack.pop();
right = new VarExpression(String.valueOf(charArray[++i]));
stack.push(new SubExpression(left, right));
break;
default:
stack.push(new VarExpression(String.valueOf(charArray[i])));
break;
}
}
this.expression = stack.pop();
}
public int run(HashMap<String, Integer> var) {
return this.expression.interpret(var);
}
}
5.创建客户端Client
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.HashMap;
public class Client {
public static void main(String[] args) throws IOException {
String expStr = getExpStr();
HashMap<String, Integer> var = getValue(expStr);
Calculator calculator = new Calculator(expStr);
System.out.println("运算结果: " + expStr + "=" + calculator.run(var));
}
public static String getExpStr() throws IOException {
System.out.println("请输入表达式: ");
return (new BufferedReader(new InputStreamReader(System.in))).readLine();
}
public static HashMap<String, Integer> getValue(String expStr) throws IOException {
HashMap<String, Integer> map = new HashMap<>();
for (char ch : expStr.toCharArray()) {//[a,+,b]
if (ch != '+' && ch != '-') {
if (!map.containsKey(String.valueOf(ch))) {
System.out.println("请输入" + String.valueOf(ch) + "的值: ");
String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
map.put(String.valueOf(ch), Integer.valueOf(in));
}
}
}
return map;
}
}
输出结果1:
请输入表达式:
a+b
请输入a的值:
10
请输入b的值:
20
运算结果: a+b=30
输出结果2:
请输入表达式:
a-b
请输入a的值:
10
请输入b的值:
5
运算结果: a-b=5
状态模式(State)
状态模式:类的行为是基于它的状态改变的。
使用场景
对象的行为依赖于它的状态,并且可以根据它的状态改变而改变它的相关行为。
实现方式
《海贼王》中剑士索隆的技能:
无刀流NoSword:空手接白刃(handToHand)
一刀流OneSword:飞龙·火焰(dragonFire)、大辰撼(shock)、狮子歌歌(lionSong)、三十六烦恼风(_36Troubles)
二刀流TwoSwords:居合·罗生门(JuheRashomon)
三刀流ThreeSwords:鬼斩(ghostChop)、虎狩(tigerHunt)、龙卷风(tornado)、三千世界(_3000Worlds)
九刀流NineSwords:阿修罗(Asura)
1.创建State接口
public interface State {
void doAction(Context context);
}
这里还没有创建Context,所以暂时会报错。
2.创建Context类
public class Context {
private State state;
public Context() {
state = null;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
}
3.创建不同的状态类(每种状态都实现State接口)
public class NoSword implements State {
@Override
public void doAction(Context context) {
System.out.println("切换到无刀流");
context.setState(this);
handToHand();
}
private void handToHand() {
System.out.println("无刀流·真剑·空手接白刃");
}
public String toString() {
return "无刀流";
}
}
public class OneSword implements State {
@Override
public void doAction(Context context) {
System.out.println("切换到一刀流");
context.setState(this);
//dragonFire();
shock();
//lionSong();
//_36Troubles();
}
private void dragonFire() {
System.out.println("一刀流·飞龙·火焰");
}
private void shock() {
System.out.println("一刀流·大辰撼");
}
private void lionSong() {
System.out.println("一刀流居合·狮子歌歌");
}
private void _36Troubles() {
System.out.println("一刀流·三十六烦恼风");
}
public String toString() {
return "一刀流";
}
}
public class TwoSwords implements State {
@Override
public void doAction(Context context) {
System.out.println("切换到二刀流");
context.setState(this);
JuheRashomon();
}
private void JuheRashomon() {
System.out.println("二刀流·居合·罗生门");
}
public String toString() {
return "二刀流";
}
}
public class ThreeSwords implements State {
@Override
public void doAction(Context context) {
System.out.println("切换到三刀流");
context.setState(this);
//ghostChop();
//tigerHunt();
//tornado();
_3000Worlds();
}
private void ghostChop() {
System.out.println("三刀流·炼狱鬼斩");
}
private void tigerHunt() {
System.out.println("三刀流·极·虎狩");
}
private void tornado() {
System.out.println("三刀流·黑绳‧大龙卷");
}
private void _3000Worlds() {
System.out.println("三刀流奥义·三千世界");
}
public String toString() {
return "三刀流";
}
}
public class NineSwords implements State {
@Override
public void doAction(Context context) {
System.out.println("切换到九刀流");
context.setState(this);
Asura();
}
private void Asura() {
System.out.println("鬼气·九刀流·阿修罗");
}
public String toString() {
return "九刀流";
}
}
4.吃瓜群众Client
public class Client {
public static void main(String[] args) {
Context context = new Context();
NoSword noSword = new NoSword();
noSword.doAction(context);
System.out.println("--------");
System.out.println(context.getState().toString());
OneSword oneSword = new OneSword();
oneSword.doAction(context);
System.out.println("--------");
System.out.println(context.getState().toString());
TwoSwords twoSwords = new TwoSwords();
twoSwords.doAction(context);
System.out.println("--------");
System.out.println(context.getState().toString());
ThreeSwords threeSwords = new ThreeSwords();
threeSwords.doAction(context);
System.out.println("--------");
System.out.println(context.getState().toString());
NineSwords nineSwords = new NineSwords();
nineSwords.doAction(context);
}
}
输出结果:
切换到无刀流
无刀流·真剑·空手接白刃
--------
无刀流
切换到一刀流
一刀流·大辰撼
--------
一刀流
切换到二刀流
二刀流·居合·罗生门
--------
二刀流
切换到三刀流
三刀流奥义·三千世界
--------
三刀流
切换到九刀流
鬼气·九刀流·阿修罗
策略模式(Strategy)
策略模式:一个类的行为或其算法可以在运行时更改。
使用场景
定义一系列算法,把它们一个个封装起来,并且使它们可以互相替换。
实现方式
同样是学生(Student),同样在学习(Study),学霸(TopStudent)好好学习(GoodGoodStudy),学渣(SlowStudent)不好好学习(BadBadStudy)。
1.创建接口Study
public interface Study {
void study();
}
2.创建实现接口的实体类
public class GoodGoodStudy implements Study {
@Override
public void study() {
System.out.println("好好学习天天向上");
}
}
public class BadBadStudy implements Study {
@Override
public void study() {
System.out.println("学习能力一般");
}
}
3.创建抽象类Student
public abstract class Student {
Study study;
public abstract void display();
public void study() {
if (study != null) {
study.study();
}
}
}
4.创建Student的子类TopStudent和SlowStudent
public class TopStudent extends Student {
public TopStudent() {
study = new GoodGoodStudy();
}
@Override
public void display() {
System.out.println("一只学霸");
}
}
public class SlowStudent extends Student {
public SlowStudent() {
study = new BadBadStudy();
}
@Override
public void display() {
System.out.println("一块学渣");
}
}
5.吃瓜群众Client
public class Client {
public static void main(String[] args) {
Student topStudent = new TopStudent();
topStudent.display();
topStudent.study();
Student slowStudent = new SlowStudent();
slowStudent.display();
slowStudent.study();
}
}
输出结果:
一只学霸
好好学习天天向上
一块学渣
学习能力一般
责任链模式(Chain of Responsibility)
责任链模式:为请求创建了一个接收者对象的链,意在对请求的发送者和接收者进行解耦。
使用场景
责任链模式通常每个接收者都包含对另一个接收者的引用,如果一个对象不能处理该请求,那么它回把相同的请求传给下一个接收者,依此类推。
实现方式
唐僧师徒四人西天取经的途中遇到许多妖精(Monster),
沙和尚(Sha)可以解决小妖(Imp);
猪八戒(Zhu)可以解决小妖和老妖(Demon);
孙悟空(Sun)可以解决小妖、老妖和妖王(DemonLord)。
1.创建妖精类Monster及其子类
public class Monster {
private String monsterType;
private int monsterLevel;
public String getMonsterType() {
return monsterType;
}
public void setMonsterType(String monsterType) {
this.monsterType = monsterType;
}
public int getMonsterLevel() {
return monsterLevel;
}
public void setMonsterLevel(int monsterLevel) {
this.monsterLevel = monsterLevel;
}
}
public class Imp extends Monster {
public Imp() {
super.setMonsterType("小妖");
super.setMonsterLevel(1);
}
}
public class Demon extends Monster {
public Demon() {
super.setMonsterType("老妖");
super.setMonsterLevel(2);
}
}
public class DemonLord extends Monster {
public DemonLord() {
super.setMonsterType("妖王");
super.setMonsterLevel(3);
}
}
2.创建妖精处理者Approver及其子类
public abstract class Approver {
String name;
Approver nextApprover;
public void setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
}
public abstract void handle(Monster monster);
}
public class Sha extends Approver {
public Sha() {
super.name = "沙和尚";
super.nextApprover = new Zhu();
}
@Override
public void handle(Monster monster) {
if (monster.getMonsterLevel() <= 1) {
System.out.println("沙和尚出马 解决掉" + monster.getMonsterType());
} else {
nextApprover.handle(monster);
}
}
}
public class Zhu extends Approver {
public Zhu() {
super.name = "猪八戒";
super.nextApprover = new Sun();
}
@Override
public void handle(Monster monster) {
if (monster.getMonsterLevel() <= 2) {
System.out.println("猪八戒出马 解决掉" + monster.getMonsterType());
} else {
nextApprover.handle(monster);
}
}
}
public class Sun extends Approver {
public Sun() {
super.name = "孙悟空";
}
@Override
public void handle(Monster monster) {
if (monster.getMonsterLevel() <= 3) {
System.out.println("孙悟空出马 解决掉" + monster.getMonsterType());
} else {
System.out.println("失去了唐僧");
}
}
}
3.吃瓜群众Client
public class Client {
public static void main(String[] args) {
Monster imp = new Imp();
Monster demon = new Demon();
Monster demonLord = new DemonLord();
Approver sha = new Sha();
Approver zhu = new Zhu();
Approver sun = new Sun();
sha.handle(imp);
sha.handle(demon);
sha.handle(demonLord);
System.out.println("--------");
zhu.handle(imp);
zhu.handle(demon);
zhu.handle(demonLord);
System.out.println("--------");
sun.handle(imp);
sun.handle(demon);
sun.handle(demonLord);
}
}
输出结果:
沙和尚出马 解决掉小妖
猪八戒出马 解决掉老妖
孙悟空出马 解决掉妖王
--------
猪八戒出马 解决掉小妖
猪八戒出马 解决掉老妖
孙悟空出马 解决掉妖王
--------
孙悟空出马 解决掉小妖
孙悟空出马 解决掉老妖
孙悟空出马 解决掉妖王
加油!