Skip to content
On this page

行为型

解释器模式

不解释

模板方法模式

有些时候,业务可能需要经历很多个步骤来完成, 比如我们生病了在医院看病,首先是去门诊挂号,然后等待叫号,然后是去找医生看病,确定病因后,就根据医生的处方去前台开药,最后付钱。 这一整套流程看似是规规矩矩的,但是在这其中,某些步骤并不是确定的,比如医生看病这一步,由于不同的病因,可能会进行不同的处理,最后开出来的药方也会不同,所以,整套流程中,有些操作是固定的,有些操作可能需要根据具体情况而定。

在我们的程序中也是如此,可能某些操作是固定的,我们就可以直接在类中对应方法进行编写,但是可能某些操作需要视情况而定,由不同的子类实现来决定,这时,我们就需要让这些操作由子类来延迟实现了。现在我们就需要用到模板方法模式。

java
/**
 * 抽象诊断方法,因为现在只知道挂号和看医生是固定模式,剩下的开处方和拿药都是不确定的
 */
abstract class AbstractDiagnosis {

    public abstract void fallIll();

    public void test() {
        this.fallIll();
        System.out.println("1 >> 先挂号");
        System.out.println("2 >> 等待叫号");
        //由于现在不知道该开什么处方,所以只能先定义一下行为,然后具体由子类实现
        //大致的流程先定义好就行
        this.prescribe();
        //开药同理
        this.medicine();
    }

    //开处方操作根据具体病症决定了
    public abstract void prescribe();

    //拿药也是根据具体的处方去拿
    public abstract void medicine();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

现在我们定义好了抽象方法,只是将具体的流程先定义出来了,但是部分方法需要根据实现决定:

java
/**
 * 感冒相关的具体实现子类
 */
class ColdDiagnosis extends AbstractDiagnosis {

    @Override
    public void fallIll() {
        System.out.println("0 >> 感冒了");
    }

    @Override
    public void prescribe() {
        System.out.println("3 >> 一眼丁真,鉴定为假,这不是感冒,纯粹是想摆烂");
    }

    @Override
    public void medicine() {
        System.out.println("4 >> 开点头孢回去吃吧");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

责任链模式

责任链模式也非常好理解,比如我们的钉钉审批,实际上就是一条流水线一样的操作,由你发起申请,然后经过多个部门主管审批,最后才能通过,所以你的申请表相当于是在一条责任链上传递。当然除了这样的直线型责任链之外,还有环形、树形等。

e6c9d24egy1h2jwlifbqfj21ci05ujrx.jpg

这里我们就使用责任链模式来模拟一个简单的面试过程,我们面试也是一面二面三面这样走的流程,这里我们先设计一下责任链上的各个处理器:

java
abstract class Handler {

    //这里我们就设计责任链以单链表形式存在,这里存放后继节点
    protected Handler successor;

    //拼接后续节点
    public Handler connect(Handler successor) {
        this.successor = successor;
        //这里返回后继节点,方便我们一会链式调用
        return successor;
    }

    public void handle() {
        //由不同的子类实现具体处理过程
        this.doHandle();
        Optional
                .ofNullable(successor)
                //责任链上如果还有后继节点,就继续向下传递
                .ifPresent(Handler::handle);
    }

    //结合上节课学习的模板方法,交给子类实现
    public abstract void doHandle();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

因为面试有很多轮,所以我们这里创建几个处理器的实现:

java
class FirstHandler extends Handler {
    //用于一面的处理器
    @Override
    public void doHandle() {
        System.out.println("============= 白马程序员一面 ==========");
    }
}

class SecondHandler extends Handler {
    @Override
    public void doHandle() {
        System.out.println("============= 白马程序员二面 ==========");
    }
}

class ThirdHandler extends Handler{
    @Override
    public void doHandle() {
        System.out.println("============= 白马程序员三面 ==========");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

开始面试

java
public static void main(String[] args) {
    Handler handler = new FirstHandler();  //一面首当其冲
    handler
            .connect(new SecondHandler())   //继续连接二面和三面
            .connect(new ThirdHandler());
    handler.handle();   //开始面试
} 
1
2
3
4
5
6
7

命令模式

比如现在我们有很多的类,彩电、冰箱、空调、洗衣机、热水器等,既然现在我们要通过一个遥控器去控制他们,那么我们就需要将控制这些电器的指令都给设计好才行,并且还不能有太强的关联性。

所有的电器肯定需要通过蓝牙或是红外线接受遥控器发送的请求,所以所有的电器都是接收者:

java
interface Receiver {
    //具体行为,这里就写一个算了
    void action();
}

//指令抽象,不同的电器有指令
abstract class Command {

    private final Receiver receiver;

    //指定此命令对应的电器(接受者)
    protected Command(Receiver receiver) {
        this.receiver = receiver;
    }

    //执行命令,实际上就是让接收者开始干活
    public void execute() {
        receiver.action();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
java
//遥控器只需要把我们的指令发出去就行了
class Controller {
    public static void call(Command command) {
        command.execute();
    }
}

class AirConditioner implements Receiver {
    @Override
    public void action() {
        System.out.println("空调已开启,呼呼呼");
    }
}

class OpenCommand extends Command {
    public OpenCommand(AirConditioner airConditioner) {
        super(airConditioner);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

通过这种方式,遥控器这个角色并不需要知道具体会执行什么,只需要发送命令即可,遥控器和电器的关联性就不再那么强了。

迭代器模式

不解释

中介者模式

比如我们想要去外面租房,但是我们怎么知道哪里有可以租的房子呢?于是我们就会上各大租房APP上去找房源,同样的,如果我们现在有房子需要出租,我们也不知道谁会想要租房子,同样的我们也会把房子挂在租房APP上展示,而当我们去租房时或是出租时,就会有一个称为中介的人来跟我们对接,实际上也是一种中介的模式。

java
class Mediator {   //房产中介
    //在出售的房子需要存储一下
    private final Map<String, String> userMap = new HashMap<>();

    //出售房屋的人,需要告诉中介他的房屋在哪里
    public void register(String address, String user){
        userMap.put(address, user);
    }

    //通过此方法来看看有没有对应的房源
    public String find(String address){
        return userMap.get(address);
    }
}

class User {   //用户可以是出售房屋的一方,也可以是寻找房屋的一方
    String name;
    String tel;

    public User(String name, String tel) {
        this.name = name;
        this.tel = tel;
    }
  
    public User find(String address, Mediator mediator){   //找房子的话,需要一个中介和你具体想找的地方
        return mediator.find(address);
    }

    @Override
    public String toString() {
        return name+" (电话:"+tel+")";
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

中介者模式优化了原有的复杂多对多关系,而是将其简化为一对多的关系,更容易理解一些。

java
public class MediatorModeMain {

    public static void main(String[] args) {
        //出租人
        User user0 = new User("刘女士", "10086");
        //找房人
        User user1 = new User("李先生", "10010");
        Mediator mediator = new Mediator();   //我是黑心中介

        //先把房子给中介挂上去
        mediator.register("上海静安汶水路白马程序员", user0);

        //开始找房子
        user1.find("上海静安汶水路下硅谷", mediator);
        //开始找房子
        user1.find("上海静安汶水路白马程序员", mediator);
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

备忘录模式

观察者模式

状态模式

策略模式

too 简单,用得too 多 ,no 想多say

访问者模式

Released under the MIT License.