观察者模式和装饰模式

Author Avatar
Euan 11月 07, 2019
  • 在其它设备中阅读本文章

观察者模式和装饰模式

一.验证观察者模式一,实现求职中心的模拟

1.实验内容和源程序

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Subject.java
public interface Subject{
public void addObserver(Observer o);
public void deleteObserver(Observer o);
public void notifyObservers();
}
Observer.java
public interface Observer{
public void hearTelephone(String heardMess);
}
SeekJobCenter.java
import java.util.ArrayList;
public class SeekJobCenter implements Subject{
String mess;
boolean changed;
ArrayList<Observer> personList;
SeekJobCenter(){
personList=new ArrayList<Observer>();
mess="";
changed=false;
}
public void addObserver(Observer o){
if(!(personList.contains(o)))
personList.add(o);
}
public void deleteObserver(Observer o){
if(personList.contains(o))
personList.remove(o);
}
public void notifyObservers(){
if(changed){
for(int i=0;i<personList.size();i++){
Observer observer=personList.get(i);
observer.hearTelephone(mess);
}
changed=false;
}
}
public void giveNewMess(String str){
if(str.equals(mess))
changed=false;
else{
mess=str;
changed=true;
}
}
}
UniverStudent.java
import java.io.*;
public class UniverStudent implements Observer{
Subject subject;
File myFile;
UniverStudent(Subject subject,String fileName){
this.subject=subject;
subject.addObserver(this); //使当前实例成为subject所引用的具体主题的观察者
myFile=new File(fileName);
}
public void hearTelephone(String heardMess){
try{ RandomAccessFile out=new RandomAccessFile(myFile,"rw");
out.seek(out.length());
byte [] b=heardMess.getBytes();
out.write(b); //更新文件中的内容
System.out.print("我是一个大学生,");
System.out.println("我向文件"+myFile.getName()+"写入如下内容:");
System.out.println(heardMess);
}
catch(IOException exp){
System.out.println(exp.toString());
}
}
}

Haigui.java

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
import java.io.*;
import java.util.regex.*;
public class HaiGui implements Observer{
Subject subject;
File myFile;
HaiGui(Subject subject,String fileName){
this.subject=subject;
subject.addObserver(this);
myFile=new File(fileName);
}
public void hearTelephone(String heardMess){
try{ boolean boo=heardMess.contains("java程序员")||heardMess.contains("软件");
if(boo){
RandomAccessFile out=new RandomAccessFile(myFile,"rw");
out.seek(out.length());
byte [] b=heardMess.getBytes();
out.write(b);
System.out.print("我是一个海归,");
System.out.println("我向文件"+myFile.getName()+"写入如下内容:");
System.out.println(heardMess);
}
else{
System.out.println("我是海归,这次的信息中没有我需要的信息");
}
}
catch(IOException exp){
System.out.println(exp.toString());
}
}
}

Application.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Application{
public static void main(String args[]){
SeekJobCenter center=new SeekJobCenter();
UniverStudent zhangLin=new UniverStudent(center,"A.txt");
HaiGui wangHao=new HaiGui(center,"B.txt");
center.giveNewMess("腾辉公司需要10个java程序员。");
center.notifyObservers();
center.giveNewMess("海景公司需要8个动画设计师。");
center.notifyObservers();
center.giveNewMess("仁海公司需要9个电工。");
center.notifyObservers();
center.giveNewMess("仁海公司需要9个电工。");
center.notifyObservers();
}
}

2.实验执行结果

Kq6FIg.png

3.本次收获体会

本问题实现观察者接口Observer的类有两个:一个是UniversityStudent的类,另一个是Haigui。UniversityStudent类的调用方法是会见参数引用的字符串保存到一个文件中。

二.验证装饰模式程序二,实现鸟类飞翔的模拟

1.实验内容和源程序

Bird.java

1
2
3
public abstract class Bird{
public abstract int fly();
}

Sparrow.java

1
2
3
4
5
6
public class Sparrow extends Bird{
public final int DISTANCE=100;
public int fly(){
return DISTANCE;
}
}

Decorator.java

1
2
3
4
5
6
7
8
public abstract class  Decorator extends Bird{
protected Bird bird;
public Decorator(){
}
public Decorator(Bird bird){
this.bird=bird;
}
}

SparrowDecorator.java

1
2
3
4
5
6
7
8
public abstract class  Decorator extends Bird{
protected Bird bird;
public Decorator(){
}
public Decorator(Bird bird){
this.bird=bird;
}
}

Application.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Application{
public void needBird(Bird bird){
int flyDistance=bird.fly();
System.out.println("这只鸟能飞行"+flyDistance+"米");
}
public static void main(String args[]){
Application client=new Application();
Sparrow sparrow=new Sparrow();
SparrowDecorator sparrowDecorator1=
new SparrowDecorator(sparrow);
SparrowDecorator sparrowDecorator2=
new SparrowDecorator(sparrowDecorator1);
client.needBird(sparrowDecorator1);
client.needBird(sparrowDecorator2);
}
}

2.实验执行结果

Kq6PZ8.png

3.本次收获体会

装饰模式中非常重要的一点就是“具体组件”和“装饰”都是“抽象组件”的子类。用户如果需要电泳“被装饰者”源氏的方法就让“抽象组件”声明的对象存放装饰者的作用。

三.设计使用多个装饰者的鸟类飞翔程序

1.实验内容和源程序

Bird.java

1
2
3
public abstract class Bird{
public abstract int fly();
}``

Sparrow.java

1
2
3
4
5
6
public class Sparrow extends Bird{
public final int DISTANCE=60;
public int fly(){
return DISTANCE;
}
}

Decorator.java

1
2
3
4
5
6
7
8
public abstract class  Decorator extends Bird{
protected Bird bird;
public Decorator(){
}
public Decorator(Bird bird){
this.bird=bird;
}
}

SparrowDecorator.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class  SparrowDecorator extends Decorator{
public final int DISTANCE=40; //eleFly方法能飞50米
SparrowDecorator(Bird bird){
super(bird);
}
public int fly(){
int distance=0;
distance=bird.fly()+eleFly(); //委托被装饰者bird调用fly(),然后再调用eleFly()
return distance;
}
private int eleFly(){ //装饰者新添加的方法
return DISTANCE;
}
}

SparrowDecoratorTwo.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class  SparrowDecoratorTwo extends Decorator{
public final int DISTANCE=20;
SparrowDecoratorTwo(Bird bird){
super(bird);
}
public int fly(){
int distance=0;
distance=bird.fly()+eleFly();
return distance;
}
public int eleFly(){
return DISTANCE;
}
}

Application.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Application{
public void needBird(Bird bird){
int flyDistance=bird.fly();
System.out.println("这只鸟能飞行"+flyDistance+"米");
}
public static void main(String args[]){
Application client=new Application();
Bird bird1=new SparrowDecoratorTwo(new Sparrow());
Bird bird2=new SparrowDecorator(bird1);
Bird bird3=new SparrowDecorator(bird2);
Bird bird4=new SparrowDecoratorTwo(bird3);
client.needBird(bird1);
client.needBird(bird2);
client.needBird(bird3);
client.needBird(bird4);
}
}

2.实验执行结果

Kq6idS.png

3.本次收获体会

由于装饰是抽象组件的一个子类,因此“装饰者”本身也可以作为一个“被装饰者”,这意味着可以使用多个具体装饰类来装饰具体组件的实例。

本文使用 CC BY-NC-SA 3.0 中国大陆 协议许可
具体请参见 知识共享协议

本文链接:https://zyhang8.github.io/2019/11/07/design-exp2/