java和设计模式(行为模式)

时间:2022-11-23 14:55:39


        和构建模式、结构模式相比较,行为模式的内容要多一些。在设计模式中,行为模式强调的是类和对象之间的交互关系。它更多强调的是,在特定的行为场景种,使用哪一种设计模式是比较合适、比较得体的。

        行为模式一般认为有11种,分别是命令模式、解释器模式、迭代模式、中介模式、备忘录模式、观察者模式、责任链模式、状态模式、策略模式、模板模式和访问者模式。

1、命令模式

        命令模式的本质,是把接收命令的人、执行命令的人做了一个解耦。这样,不同的命令就成了一个个独立的个体。一个比较贴切的案例就是餐馆。餐馆里面的服务员会接收各种各样的服务要求,比如来一盘炒菜、来一个汤、来一份主食。这些点菜服务都可以看成是命令。把这些命令独立出来,并且把命令匹配给对应的执行者,这就是命令模式设计的初衷了。如果要画成类图,应该是这样的,

java和设计模式(行为模式)

        如果把上述图形换成java代码,应该是这样的,

import java.io.*;

class receiver
{
public void process(String s)
{
System.out.println(s);
}
}

class command
{
public void execute()
{
return;
}
}

class commandA extends command
{
private receiver r;

public commandA(receiver r)
{
this.r = r;
}

public void execute()
{
r.process("A command");
}
}

class commandB extends command
{
private receiver r;

public commandB(receiver r)
{
this.r = r;
}

public void execute()
{
r.process("B command");
}
}

class commandC extends command
{
private receiver r;

public commandC(receiver r)
{
this.r = r;
}

public void execute()
{
r.process("C command");
}
}

class waiter
{
private command cmdA;
private command cmdB;
private command cmdC;

public void setCmdA(command cmd)
{
this.cmdA = cmd;
}

public void setCmdB(command cmd)
{
this.cmdB = cmd;
}

public void setCmdC(command cmd)
{
this.cmdC = cmd;
}

public void exeCmdA()
{
this.cmdA.execute();
}

public void exeCmdB()
{
this.cmdB.execute();
}

public void exeCmdC()
{
this.cmdC.execute();
}
}

public class commandDemo
{
public static void main(String[] args)
{
waiter w = new waiter();

receiver r = new receiver();
command a = new commandA(r);
command b = new commandB(r);
command c = new commandC(r);

w.setCmdA(a);
w.setCmdB(b);
w.setCmdC(c);

w.exeCmdA();
w.exeCmdB();
w.exeCmdC();

}
}

2、解释器模式

        解释器模式,比较合适拿来类比的就是编译器。每一种编程语言都有自己的文法格式,或者称之为范式。那么这些范式就是一个一个小的解释器。最简单的解释器就是int a;这种。复杂一点的解释器就是if-statement、for-statement、while-statement这种。所以,这是如果把解析的接口抽象出来,其实就是解释器模式,

java和设计模式(行为模式)

        如果写一个编译器,过于复杂,我们可以写一个小的解释器。比如识别ab、aabb、aaabbb、a**b这样的字符串,这样也可以说明问题,

abstract class interpret
{
abstract public boolean parse(String str);
}

class terminate extends interpret
{
public boolean parse(String str)
{
if(str.charAt(0)== 'a' && str.charAt(1) == 'b')
{
return true;
}
else
{
return false;
}
}
}

class block extends interpret
{
private interpret it;
boolean result;
int size;

public boolean parse(String str)
{
size = str.length();
if(size < 2)
{
return false;
}

if(size == 2)
{
it = new terminate();
result = it.parse(str);
return result;
}

if(str.charAt(0) != 'a' || str.charAt(size-1) != 'b')
{
return false;
}

it = new block();
result = it.parse(str.substring(1, size-1));
return result;
}
}

public class file
{
public static void main(String[] args)
{
interpret it = new block();
System.out.println(it.parse("a"));
System.out.println(it.parse("ab"));
System.out.println(it.parse("aab"));
System.out.println(it.parse("aabb"));
}
}

3、迭代器模式

        迭代器模式,这个大家用的比较多。不管是c++,还是java都有对应的案例。假设有一个vector<int>的向量数组,那么就可以生成一个对应的迭代器,即vector<int>::iterator。有了这个迭代器,就可以用来增删改查,还可以灵活匹配各种算法。

java和设计模式(行为模式)

        目前java就有对应的iterator范例,是这样的,

import java.util.ArrayList;
import java.util.Iterator;

public class file {
public static void main(String[] args) {

ArrayList<Integer> sites = new ArrayList<Integer>();
sites.add(1);
sites.add(2);
sites.add(3);
sites.add(4);

Iterator<Integer> it = sites.iterator();

while(it.hasNext()) {
System.out.println(it.next());
}
}
}

4、中介者模式

        中介者模式,顾名思义,就是之前两个对象完全没有联系,必须找一个共同的中介,才能完成信息的传递工作。现实场景中的群消息就是这种机制。一个人如果需要在群里面接收到其他人发送的消息,那就必须要绑定群组这个中介才可以。还有一个例子就是房屋买卖。房东和买房者之间一般都是不认识的,房屋交易想要达成,大多数情况下都要依赖于房产中介的协调和沟通。

java和设计模式(行为模式)

    如果把图形转成java代码,应该是这样的,

class mediator
{
public human[] humans = {null, null};

public void add_human(human h)
{
int i;

for(i = 0; i < 2; i++)
{
if(humans[i] == null)
{
humans[i] = h;
return;
}
}
}

public void notify(human h, String msg)
{
for(int i = 0; i < 2; i++)
{
if(humans[i] != h)
{
humans[i].receive(msg);
}
}
}
}

abstract class human
{
protected mediator m;

public human(mediator m)
{
this.m = m;
m.add_human(this);
}

abstract public void send(String msg);
abstract public void receive(String msg);
}

class A extends human
{
public A(mediator m)
{
super(m);
}

@Override
public void send(String msg)
{
System.out.println("send from " + msg +" A");
m.notify(this, msg);

}

@Override
public void receive(String msg)
{
System.out.println("receive to " + msg +" A");
}
}

class B extends human
{
public B(mediator m)
{
super(m);
}

@Override
public void send(String msg)
{
System.out.println("send "+ msg +" from B");
m.notify(this, msg);

}

@Override
public void receive(String msg)
{
System.out.println("receive "+msg +" to B");
}
}


public class mediatorDemo
{
public static void main(String []args) {
mediator m = new mediator();
human a = new A(m);
human b = new B(m);

a.send("1");
b.send("2");
a.send("3");
b.send("4");

}
}

    

5、备忘录模式

        有过Windows操作系统经验的同学都知道,在OS出现复杂问题的时候,一般微软都会有一个选项,就是将OS恢复到之前的某个时间点。这样没有大问题的话,系统又能重新启用,不需要重装系统了。备忘录就是这么一种模式,在不同的时间点做一个备份处理,

java和设计模式(行为模式)

        如果把图形换算成代码,应该是这样的,

import java.io.*;

class memo
{
private int state;

public void set_state(int state)
{
this.state = state;
}

public int get_state()
{
return this.state;
}
}

class context
{
private int state;

public void set_state(int state)
{
this.state = state;
}

public int get_state()
{
return this.state;
}

public memo gen_memo()
{
memo m = new memo();
m.set_state(state);
return m;
}

public void restore_memo(memo m)
{
this.state = m.get_state();
}
}


class manager
{
private memo m;

public void set_memo(memo m)
{
this.m = m;
}

public memo get_memo()
{
return this.m;
}

}

public class memoDemo
{
public static void main(String[] args)
{
context c = new context();
c.set_state(0);

manager m = new manager();
memo m1 = c.gen_memo();
m.set_memo(m1);
c.set_state(1);

memo m2 = m.get_memo();
c.restore_memo(m2);
}
}

6、观察者模式

。目前前端开发中使用比较多的一种架构,vue.js就是用了观察者模式。有了观察者模式,编写前端的同学就可以把数据和渲染做一个解耦。数据发生改变,vue.js会自动帮助渲染。同样而言,如果有用户操作了外部控件(类似于滑动条),对应的数据也会自动发生改变。用类图来表示的话,是这样一种情形,

java和设计模式(行为模式)

    如果把图形转成java代码,应该是这样的,

class event
{
public observer[] obs = {null, null, null};

public void register(observer o)
{
for(int i = 0; i < 3; i++)
{
if(null == obs[i])
{
obs[i] = o;
break;
}
}
}

public void process()
{
for(int i = 0; i < 3; i++)
{
obs[i].notify_msg();
}
}
}

class observer
{
private event e;

public observer(event e)
{
this.e = e;
e.register(this);
}

public void notify_msg()
{
return;
}
}

class observer1 extends observer
{
public observer1(event e)
{
super(e);
}

@Override
public void notify_msg()
{
System.out.println("notify observer1");
}
}

class observer2 extends observer
{
public observer2(event e)
{
super(e);
}

@Override
public void notify_msg()
{
System.out.println("notify observer2");
}
}

class observer3 extends observer
{
public observer3(event e)
{
super(e);
}

@Override
public void notify_msg()
{
System.out.println("notify observer3");
}
}


public class observerDemo
{
public static void main(String []args) {
event e = new event();

observer o1 = new observer1(e);
observer o2 = new observer2(e);
observer o3 = new observer3(e);

e.process();
}
}

7、责任链模式

        责任链模式是很容易和现实场景联系在一起的设计模式。比如说出差需要报销发票,这个时候不同的领导额度是不一样的,比如低于300科长可以报销,低于1000部长可以报销,低于5000可能就要总经理报销了。责任链也就是这个道理,

java和设计模式(行为模式)

        责任链用的也比较多,java代码是这样的,

import java.io.*;

class employee
{
protected employee next;

public employee(employee next)
{
this.next = next;
}

public void check(int e)
{
return;
}
}

class employeeA extends employee
{
public employeeA(employee next)
{
super(next);
}

@Override
public void check(int e)
{
if(e < 100)
{
System.out.println("OK for employeeA");
}
else if(null != next)
{
next.check(e);
}
else
{
System.out.println("fail for employeeA");
}
}
}

class employeeB extends employee
{
public employeeB(employee next)
{
super(next);
}

@Override
public void check(int e)
{
if(e < 1000)
{
System.out.println("OK for employeeB");
}
else if(null != next)
{
next.check(e);
}
else
{
System.out.println("fail for employeeB");
}
}
}

public class chainDemo
{
public static void main(String[] args)
{
employee e1 = new employeeB(null);
employee e2 = new employeeA(e1);

e2.check(50);
e2.check(500);
e2.check(1000);

return;
}
}

8、状态模式

        状态模式其实和状态机是一个道理。不管是软件设计,还是fpga硬件设计,状态机都是使用比较多的一种方式。状态机很容易就构建一个封闭、鲁棒的系统。而设计模式,只是告诉我们如何用面向对象的语言来构建状态模式,

java和设计模式(行为模式)

        图形如果写成代码,应该是这样的,

class context
{
public state s;

public void set_state(state s)
{
this.s = s;
}

public void handle_context()
{
s.handle(this);
}
}

interface state
{
public void handle(context c);
}

class state1 implements state
{
@Override
public void handle(context c)
{
c.set_state(new state2());
System.out.println("state1");
}
}

class state2 implements state
{
@Override
public void handle(context c)
{
c.set_state(new state3());
System.out.println("state2");
}
}

class state3 implements state
{
@Override
public void handle(context c)
{
c.set_state(new state1());
System.out.println("state3");
}
}

public class stateDemo
{
public static void main(String []args) {
context c = new context();
c.set_state(new state1());

c.handle_context();
c.handle_context();
c.handle_context();

}
}

9、策略模式

        策略模式有点类似于算法接口。不管是什么算法,对外的抽象接口都是一样的,这样对于输入数据而言,只需要在实际使用的时候,选择对应的算法,也就是对应的策略就可以了。策略模式一般和上面谈到的迭代器模式配合使用,

java和设计模式(行为模式)

        如果把策略转换成代码,应该是这样的,

import java.io.*;

class strategy
{
void method(int x, int y)
{
return;
}
}

class strategyA extends strategy
{
@Override
public void method(int x, int y)
{
System.out.println(x+y);
}
}

class strategyB extends strategy
{
@Override
public void method(int x, int y)
{
System.out.println(x*y);
}
}

class user
{
private int x;
private int y;

public user(int x, int y)
{
this.x = x;
this.y = y;
}

public void set_strategy(strategy s)
{
s.method(x,y);
}

}

public class strategyDemo
{
public static void main(String[] args)
{
user u = new user(3,4);
u.set_strategy(new strategyA());
u.set_strategy(new strategyB());
}
}

10、模板模式

        模板模式比较有意思。有一些产品的制作流程是比较类似的,但是制作流程需要拆分成几个步骤。在每一个步骤里面,具体实施的细节又不一样。那么这个时候,就需要将每一个步骤的接口抽象出来,同时在顶层构建一个总的制作流程。这就好比,有一个统一的模板给你参考,每一个步骤也都是约定好的,但是具体每个步骤里面做什么是需要自己定义好的,

java和设计模式(行为模式)

        把上述图形换成java代码,应该是这样的,

class template
{
public void process()
{
processA();
processB();
processC();
}

public void processA()
{
return;
}

public void processB()
{
return;
}

public void processC()
{
return;
}
}

class templateA extends template
{
public void processA()
{
System.out.println("templateA processA");
}

public void processB()
{
System.out.println("templateA processB");
}

public void processC()
{
System.out.println("templateA processC");
}
}

class templateB extends template
{
public void processA()
{
System.out.println("templateB processA");
}

public void processB()
{
System.out.println("templateB processB");
}

public void processC()
{
System.out.println("templateB processC");
}
}

public class templateDemo
{
public static void main(String []args) {
template t1 = new templateA();
t1.process();

template t2 = new templateB();
t2.process();
}
}

11、访问者模式

        在个人印象中,访问者模式用的很少。有这么一种场景,画画需要绘制各种物体,而画画本身又可以分为水墨、油画、素描等各种艺术形式。这时,为了实现绘画和具体物体之间的解耦,有必要设计一种模式来完成这一目的,我们可以先看一下这个类图,

java和设计模式(行为模式)

       上图中的element就是各种物体,visitor就是各种画画艺术。每种物体想通过具体的艺术形式呈现出来,这就需要visitor来帮忙了。element和visitor是通过入参来完成关联的,这是一种轻量耦合的方式。

        上述图形如果要用java代码表示,可以这么写

import java.io.*;

abstract class visitor
{
abstract public void access1(element1 e1);
abstract public void access2(element2 e2);
}

class visitor1 extends visitor
{
@Override
public void access1(element1 e1)
{
System.out.println("element1 in visitor1");
}

@Override
public void access2(element2 e2)
{
System.out.println("element2 in visitor1");
}

}

class visitor2 extends visitor
{
@Override
public void access1(element1 e1)
{
System.out.println("element1 in visitor2");
}

@Override
public void access2(element2 e2)
{
System.out.println("element2 in visitor2");
}
}

abstract class element
{
abstract public void accept(visitor v);
}

class element1 extends element
{
@Override
public void accept(visitor v)
{
v.access1(this);
System.out.println("element1 processing");
}
}

class element2 extends element
{
@Override
public void accept(visitor v)
{
v.access2(this);
System.out.println("element2 processing");
}
}


public class visitDemo
{
public static void main(String[] args)
{
element e1 = new element1();
element e2 = new element2();

visitor v1 = new visitor1();
visitor v2 = new visitor2();

e1.accept(v1);
e1.accept(v2);
e2.accept(v1);
e2.accept(v2);
}
}

12、其他

        虽然一下子把行为模式的11种情形都简单描述了一下,但是个人理解和实际应用往往还需要花费很多的时间的。一方面,不需要死记硬背,机械地去套用;另外一方面,软件工程也在快速发展,不能认为23种设计模式已经包含了所有的开发套路,实际应用中活学活用就好了。学习的目的不在于记忆,而在于使用和改进。