讨伐设计模式——行为型模式篇

本文是学习设计模式时做的笔记,原视频链接:

https://www.bilibili.com/video/BV1G4411c7N4

目录

模板方法模式(Template Method)

使用场景

实现方式

命令模式(Command)

使用场景

实现方式

访问者模式(Visitor)

使用场景

实现方式

迭代器模式(Iterator)

使用场景

实现方式

观察者模式(Observer)

使用场景

实现方式

中介者模式(Mediator)

使用场景

实现方式

备忘录模式(Memento)

使用场景

实现方式

解释器模式(Interpreter)

使用场景

实现方式

状态模式(State)

使用场景

实现方式

策略模式(Strategy)

使用场景

实现方式

责任链模式(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);
    }
}

输出结果:

沙和尚出马 解决掉小妖
猪八戒出马 解决掉老妖
孙悟空出马 解决掉妖王
--------
猪八戒出马 解决掉小妖
猪八戒出马 解决掉老妖
孙悟空出马 解决掉妖王
--------
孙悟空出马 解决掉小妖
孙悟空出马 解决掉老妖
孙悟空出马 解决掉妖王

加油!

猜你喜欢

转载自blog.csdn.net/qq_42082161/article/details/112770667