Balking
设计模式
针对
Balking设计模式,我们先结合一下现实生活中的例子来认识一下它。我们在餐馆点餐,想好之后,举手示意服务员点菜,于是,看到我举手的服务员就向我走过来,但这时,另一位服务员也看到我举手示意了,但她看到已经有一位服务员走向了我,所以就没有再过来
......
如果现在不适合执行这个操作,或者没必要执行这个操作,就停止处理,直接返回
-----这就是我们介绍的
Balking
模式。
我们来看一下
Balking模式的简单示例程序,这个程序会定期地将当前数据内容写入文件中。当数据内容被写入时,会完全覆盖上次写入的内容,只有最新的内容才会被保存。另外,当写入内容和上次写入的内容完全相同时,再向文件写入就显得多余了,所以就不再执行写入操作。也就是说,该程序以“数据内容存在不同”作为守护条件,如果数据内容相同,则不执行写入操作,直接返回(
Balk
)。
在这里我们来思考一下文本工具的
“自动保存功能”,所谓自动保存功能,就是为了防止电脑突然死机,而定期地将数据保存到文本中的功能。下面该示例程序可以说是自动保存功能的超级精简版。先介绍一下用到的一下类:
Data表示可以修改并保存的
数据的类
,对应文本工具的文本内容;
SaverThread定期保存数据的内容的类,对应的是
执行自动保存的线程
;
ChangerThread是模仿“进行文本修改并随时保存的用户”,对应着的是
修改并保存数据内容的类
。Data
类用于表示当前数据。
filename
字段是执行保存的文件名称
content
字段是表示数据内容的字符串,也就是写入文件的内容。
changed
字段用于表示自上次保存之后,
Content
字段是否又进行了修改,
changed
字段的值为
true
时表示进行了修改,为
false
则为未修改,程序根据
changed
的值决定要不要执行文件写入。这种表示两种状态的字段和变量,我们通常称之为
(flag)
。这里,“
changed
字段标志位
true
”便是守护条件。
Data
类中用于修改数据内容的方法(
change
),以及要求将数据内容保存到文件中的方法
(save)
。另外还有一个实际执行文件保存的方法
(doSave)
。
在
change方法中,新的数据内容会被赋予到
content
字段,同时,
changed
字段会被设置为
true
,这表示内容进行了修改。
Change
和
save
这两个方法都被声明了
synchronized
方法,我们都知道,当看到
synchronized
时我们需要思考一下在保护着什么,在这里,我们保护的是
content
和
changed
字段。
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Data {
private final String filename; //
保存的文件名称
private String content; //
数据内容
private Boolean changed;//
修改后的文件尚未保存时,为
true
public Data(String filename, String content) {
this.filename = filename;
this.content = content;
this.changed = true;
}
//
修改数据内容
public synchronized void change(String newContent) {
content = newContent;
changed = true; //
为了表示
content
字段内容与文件内容不一致,未修改状态
}
//
若数据内容修改过,则保存到文件中
public synchronized void save() throws IOException {
if (!changed) {
return;
}
doSave();
changed = false; //
为了表示
content
字段内容与文件内容一致,未修改状态
}
private void doSave() throws IOException {
System.out.println(Thread.currentThread().getName() + "calls doSave,content=" + content);
Writer writer = new FileWriter(filename);
writer.write(content);
writer.close();
}
}
SaverThread
类用于定期保存数据内容
在
run方法中每隔一秒就调用一次
Data
实例的
save
方法,如果文件操作发生错误,
IOException异常被抛出,该线程就会终止运行。import java.io.IOException;
import com.balking.pojo.Data;
public class SaverThread extends Thread{
private final Data data;
public SaverThread(String name,Data data) {
super(name);
this.data = data;
}
public void run() {
try {
while (true) {
data.save(); //
要求保存数据
Thread.sleep(1000); //
休眠约
1
秒
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ChangerThread
类用于修改数据内容,并执行保存处理
启动的线程以”No.0”,”No.1”,”No.2”, ...
字符串为参数,循环调用
change
方法来修改数据。每修改完一个数据,线程都会“执行点别的操作”(实际上只是使用了
sleep
方法随机暂停了一段时间),然后调用
save
方法保存数据。这用来表示“将刚才修改的数据反映到文件中”。
注意
Data类的
doSave
方法每次都是重新创建文件。由于在重新创建之后,文件内容会全部消失,所以该该示例并不能直接用作应用程序的自动保存功能。实际上,实现自动保存功能时,文件必须要进行备份。
import java.io.IOException;
import java.util.Random;
import com.balking.pojo.Data;
public class ChangerThread extends Thread{
private final Data data;
private final Random random = new Random();
public ChangerThread(String name,Data data) {
super(name);
this.data = data;
}
public void run() {
try {
for (int i = 0; true; i++) {
data.change("No."+i); //
修改数据
Thread.sleep(random.nextInt(1000)); //
执行其他操作
data.save(); //
显示地保存
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Main
类运行:两个线程都执行了
doSave方法。请注意:不管是哪种情况,
content字段的内容都“不是重复保存的”(没有重复的编号)
,
这是因为
content
内容相同时,线程就会
Balk
出,不再调用
doSave
方法。
import com.balking.pojo.Data;
import com.balking.thread.ChangerThread;
import com.balking.thread.SaverThread;
public class Main {
public static void main(String[] args) {
Data data = new Data("data.txt","emtity");
new ChangerThread("ChangerThread", data).start();
new SaverThread("SaverThread",data).start();
}
}
运行结果:

也可参考时序图:

这就是我们介绍的
Balking模式
---
对象本身拥有状态,该对象只有在自身状态合适时才会执行处理,否则便不会执行处理。
我们首先将对象的合适状态表示为守护条件。然后再处理之前,检查守护条件是否成立,只有当守护条件成立时,对象才会继续执行处理,如果守护条件不成立,则不执行处理,立即从方法中返回。
更多技术资讯可关注:gzitcast