观察者模式
说明
观察者模式的组成
– 抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类或接口来实现。
- 抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
– 具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个子类实现。
– 具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。通常用一个子类实现
Watched.java
package com.vvvv.observer;
//抽象主题角色
public interface Watched{
//添加观察者
public void addWatcher(Watcher watcher);
//删除观察者
public void removeWatcher(Watcher watcher);
//传入指定的字符串,通知观察者
public void notifyWatchers(String str);
}
Watcher.java
package com.vvvv.observer;
//抽象观察者
public interface Watcher{
//根据接收到的字符串,更新自已
public void update(String str);
}
ConcreteWatched.java
package com.vvvv.observer;
import java.util.ArrayList;
import java.util.List;
//具体的主题角色
public class ConcreteWatched implements Watched{
//观察者集合
private List<Watcher> list = new ArrayList<Watcher>();
public void addWatcher(Watcher watcher){
list.add(watcher);
}
public void removeWatcher(Watcher watcher){
list.remove(watcher);
}
public void notifyWatchers(String str){
//遍历观察者集合,并调用观察者的更新方法
for(Watcher watcher : list){
watcher.update(str);
}
}
}
ConcreteWatcher.java
package com.vvvv.observer;
//具体的观察者
public class ConcreteWatcher implements Watcher{
//更新
public void update(String str){
System.out.println(str);
}
}
客户端测试类Test.java
package com.vvvv.observer;
//客户端
public class Test{
public static void main(String[] args){
//定义一个美女作为主题
Watched girl = new ConcreteWatched();
//定义三个追求者作为观察者
Watcher watcher1 = new ConcreteWatcher();
Watcher watcher2 = new ConcreteWatcher();
Watcher watcher3 = new ConcreteWatcher();
//将三个追求者添加到对美女的粉丝列表中
girl.addWatcher(watcher1);
girl.addWatcher(watcher2);
girl.addWatcher(watcher3);
//当美女发出消息说:"开心,爽",将会触发粉丝也跟着说:"开心,爽"
girl.notifyWatchers("开心,爽");
//美女从粉丝列表删除第二个粉丝
girl.removeWatcher(watcher2);
//美女再次发出消息说
girl.notifyWatchers("不爽");
}
}
Observable 与 Observer 的应用
/**
* An object may be observed by two or more
* observers.
*/
import java.util.*;
// This is the class being observed.
class BeingWatched extends Observable {
void counter(int period) {
for (; period >= 0; period--) {
setChanged();
notifyObservers(new Integer(period));
try {
Thread.sleep(100);
}catch (InterruptedException e) {
System.out.println("Sleep interrupted");
}
}
}
}
// This is the first observing class.
class Watcher1 implements Observer {
public void update(Observable obj, Object arg) {
System.out.println("watcher1's update() called, count is " +
( (Integer) arg).intValue());
}
}
// This is the second observing class.
class Watcher2 implements Observer {
public void update(Observable obj, Object arg) {
if ( ( (Integer) arg).intValue() <= 5) {
System.out.println("watcher2's update() called, count is " +
( (Integer) arg).intValue());
}
// Ring bell when done
if ( ( (Integer) arg).intValue() == 0) {
System.out.println("Done" + '\7');
}
}
}
/**
* client
*/
public class TwoObservers {
public static void main(String args[]) {
BeingWatched observed = new BeingWatched();
Watcher1 observing1 = new Watcher1();
Watcher2 observing2 = new Watcher2();
// add both observers
observed.addObserver(observing1);
observed.addObserver(observing2);
observed.counter(10);
}
}
内部类
静态内部类
package com.vvvv.innerclass;
class StaticInner{
private static int a = 4;
//静态内部类
public static class Inner{
public void test(){
System.out.println(a);
}
}
}
public class StaticInnerClassTest{
public static void main(String[] args){
StaticInner.Inner inner = new StaticInner.Inner();
inner.test();
}
}
成员内部类
package com.vvvv.innerclass;
class MemberInner{
private int a = 4;
//成员内部类
public class Inner2{
private int a = 5;
public void doSomething(){
//访问内部类的变量a
System.out.println(this.a);
System.out.println(a);
//访问外部类的变量a
System.out.println(MemberInner.this.a);
}
}
public void method(){
Inner2 inner = this.new Inner2();
}
}
public class MemberInnerClassTest{
public static void main(String[] args){
MemberInner.Inner2 inner = (new MemberInner()).new Inner2();
inner.doSomething();
}
}
局部内类部
package com.vvvv.innerclass;
class LocalInner{
public void doSomething(){
//外部类的变量要想被局部内部类访问到,必须定义成终态
final int a = 4;
//局部内部类
class Inner3{
public void test(){
System.out.println(a);
}
}
new Inner3().test();
}
}
public class LocalInnerClassTest{
public static void main(String[] args){
LocalInner localInner = new LocalInner();
localInner.doSomething();
}
}
匿名内部类
package com.vvvv.innerclass;
import java.util.Date;
public class AnonymousInnerClassTest{
@SuppressWarnings("deprecation")
public String get(Date date){
return date.toLocaleString();
}
public static void main(String[] args){
AnonymousInnerClassTest test = new AnonymousInnerClassTest();
//String str = test.get(new Date());;
//System.out.println(str);
//匿名内部类
String str = test.get(new Date(){
public String toLocaleString(){
return "hello world";
}
});
System.out.println(str);
}
}
输入输出 I/O
使用FilenameFilter
– 希望能够限制由list( )方法返回的文件数目,使它仅返回那些与一定的文件名方式或者过滤(filter)相匹配的文件。为达到这样的目的,必须使用list( )的第二种形式 (方法重载)
– String[ ] list(FilenameFilter FFObj)
– 该形式中,FFObj是一个实现FilenameFilter接口的类的对象
FilenameFilter仅定义了一个方法,accept( )。该方法被列表中的每个文件调用一次。它的通常形式如下:boolean accept(File directory, String filename)
当被directory 指定的目录中的文件(也就是说,那些与filename 参数匹配的文件)包含在列表中时,accept( )方法返回true ,当这些文件没有包括在列表中时,accept( )返回false.
package com.vvvv.io;
import java.io.File;
import java.io.FilenameFilter;
public class FileTest7{
public static void main(String[] args){
File file = new File("C:\\abc\\xyz\\hello");
//策略模式的应用
String[] names = file.list(new FilenameFilter(){
public boolean accept(File dir, String name){
if(name.endsWith(".txt")){
return true;
}
return false;
};
});
for(String name : names){
System.out.println(name);
}
}
}
用InpubStream读取文件
package com.vvvv.io2;
import java.io.FileInputStream;
import java.io.InputStream;
public class InputStreamTest1{
public static void main(String[] args) throws Exception{
InputStream is = new FileInputStream("c:/hello.txt");
byte[] buffer = new byte[200];
int length = 0;
//每次从流中读取200个字节放到buffer里,如果最后一次不足200,length即等于
//实际读到的字节数,如果读指针已经到达文件尾,则返回-1
while(-1 != (length = is.read(buffer, 0, 200))){
//将buffer中从指定位置0开始、长度为length的字节转换成字符串
String str = new String(buffer,0, length);
System.out.println(str);
}
is.close();
}
}
递归列出指定目录下的子目录与文件
package com.vvvv.io2;
import java.io.File;
import java.util.ArrayList;
//列出指定目录下的目录与文件的层次
public class ListAllTest{
//用于判断目录或文件所处的层次
private static int time;
// 递归的方法
public static void deepList(File file){
if (file.isFile() || 0 == file.listFiles().length){
return;
}else{
File[] files = file.listFiles();
files = sort(files);
for(File f : files){
StringBuffer output = new StringBuffer();
if(f.isFile()){
output.append(getTabs(time));
output.append(f.getName());
}else{
output.append(getTabs(time));
output.append(f.getName());
output.append("\\");
}
System.out.println(output);
if(f.isDirectory()){
time++;
deepList(f);
time--;
}
}
}
}
// 整理文件数组,使得目录排在文件之前
private static File[] sort(File[] files){
ArrayList<File> sorted = new ArrayList<File>();
// 寻找到所有的目录
for (File f : files){
if (f.isDirectory()){
sorted.add(f);
}
}
// 寻找到所有的文件
for (File f : files){
if (f.isFile()){
sorted.add(f);
}
}
return sorted.toArray(new File[files.length]);
}
//判断需要加多少 tab的方法
private static String getTabs(int time){
StringBuffer buffer = new StringBuffer();
for(int i = 0; i < time; i++){
buffer.append("\t");
}
return buffer.toString();
}
public static void main(String[] args){
File file = new File("C:\\Projects\\wsclient");
deepList(file);
}
}