观察者设计模式:
- 观察者设计模式解决的问题时当一个对象发生指定的动作时,要通过另外一个对象做出相应的处理。(类似事件监听)
需求
编写一个气象站、一个工人两个类,当气象站更新天气 的时候,要通知人做出相应的处理。
不用设计模式的解决思路:
(1)编写气象站类
public class WeatherStation {
String[] weathers={"晴天","雾霾", "刮风","冰雹","下雪"};
//当前天气
String weather ;
//开始工作
public void startWork()throws Exception {
Random random = new Random();
while(true){
updateWeather();//每1-5秒更新一次天气 1000~1500
int s = random.nextInt(501)+1000;
Thread.sleep(s);
}
}
//更新天气的方法
public void updateWeather(){
Random random=new Random();//随机抓天气
int index=random.nextInt(weathers.length);//随机产生一个索引值
weather = weathers[index];
System.out.println("当前的天气是: " + weather);
}
}
(2)编写工人类
public class Emp {
String name;
public Emp(String name) {
this.name = name;
}
//人是要根据天气做出相应的处理的。 "晴天","雾霾","刮风","冰雹","下雪"
public void notifyWeather(String weather){
if("晴天".equals(weather)){
System.out.println(name+"高高兴兴的去上班!!");
}else if("雾霾".equals(weather)){
System.out.println(name+"戴着消毒面具去上班!");
}else if("刮风".equals(weather)){
System.out.println(name+"拖着大石头过来上班!");
}else if("冰雹".equals(weather)){
System.out.println(name+"戴着头盔过来上班!");
}else if("下雪".equals(weather)){
System.out.println(name+"戴着被子过来上班!");
}
}
}
(2)编写主类运行
public class WeatherMain {
//气象站在不断的更新的天气
public static void main(String[] args) throws Exception {
WeatherStation station=new WeatherStation();
station.startWork();
//工人
Emp e=new Emp("小明");
Random random=new Random();
while(true){
e.notifyWeather(station.weather);
int s=random.nextInt(501)+1000;
Thread.sleep(s);
}
}
}
运行后的问题1:
随机数产生不一致,导致运行结果出现问题。
气象站更新了多次天气,然后人才做一次的处理。
解决思路:
气象站主动通知人的,能否在气象站类维护一个工人,在气象站创建的时候传入这个人,气象站更新方法的时候 ,这个人更新天气?
代码如下
WeatherStation类:
package qqq;
import java.util.Random;
public class WeatherStation {
String[] weathers={"晴天","雾霾", "刮风","冰雹","下雪"};
//当前天气
String weather ;
//人
Emp e;
public WeatherStation(Emp e){
this.e=e;
}
//开始工作
public void startWork()throws Exception {
Random random = new Random();
new Thread(){
public void run() {
while(true){
updateWeather();//每1-5秒更新一次天气 1000~1500
e.notifyWeather(weather);
int s = random.nextInt(501)+1000;
try {
Thread.sleep(s);
} catch (Exception e) {
e.printStackTrace();
}
}
};
}.start();
}
//更新天气的方法
public void updateWeather(){
Random random=new Random();//随机抓天气
int index=random.nextInt(weathers.length);//随机产生一个索引值
weather = weathers[index];
System.out.println("当前的天气是: " + weather);
}
}
WeatherMain:
public class WeatherMain {
//气象站在不断的更新的天气
public static void main(String[] args) throws Exception {
//工人
Emp e=new Emp("小明");
Random random=new Random();
WeatherStation station=new WeatherStation(e);
station.startWork();
}
}
运行后的问题2:
目前气象站只能通知一个工人而已。如果还有其他人怎么办?
解决思路:
能否把小明放入集合中,用集合来存储一堆人,这样解决?
重新修改WeatherStation代码:
public class WeatherStation {
String[] weathers={"晴天","雾霾", "刮风","冰雹","下雪"};
//当前天气
String weather ;
//工人集合
ArrayList<Emp>list=new ArrayList<Emp>();
public void addListener(Emp e){
list.add(e);
}
//开始工作
public void startWork()throws Exception {
Random random = new Random();
new Thread(){
public void run() {
while(true){
updateWeather();//每1-5秒更新一次天气 1000~1500
//便利集合,挨个通知工人
for(Emp e:list){
e.notifyWeather(weather);
}
int s = random.nextInt(501)+1000;
try {
Thread.sleep(s);
} catch (Exception e) {
e.printStackTrace();
}
}
};
}.start();
}
//更新天气的方法
public void updateWeather(){
Random random=new Random();//随机抓天气
int index=random.nextInt(weathers.length);//随机产生一个索引值
weather = weathers[index];
System.out.println("当前的天气是: " + weather);
}
}
主类运行:
public class WeatherMain {
//气象站在不断的更新的天气
public static void main(String[] args) throws Exception {
//工人
Emp e=new Emp("小明");
Emp e2=new Emp("如花");
Random random=new Random();
WeatherStation station=new WeatherStation();
station.addListener(e);
station.addListener(e2);
station.startWork();
}
}
运行后的问题3:
在现实生活中除了工人群体要关注天气,其他的群体也需要关注天气怎么办??学生群体关注天气怎么办??
解决思路:
观察者设计模式:
添加一个接口,让学生类、工人类去实现这个接口的方法,气象站类创建集合存储接口对象,气象站开始工作的时候去遍历集合,更新通知。
代码如下:
学生类:
public class Student implements Weather{
String name;
public Student(String name) {
super();
this.name = name;
}
public void notifyWeather(String weather){
if("晴天".equals(weather)){
System.out.println(name+"高高兴兴的去开学!!");
}else if("雾霾".equals(weather)){
System.out.println(name+"吸多两口去上学!");
}else if("刮风".equals(weather)){
System.out.println(name+"在家睡觉!");
}else if("冰雹".equals(weather)){
System.out.println(name+"在家睡觉!");
}else if("下雪".equals(weather)){
System.out.println(name+"等下完再去上学!");
}
}
}
工人类:
package cn.itcast.observer;
//人 是要根据天气做出相应的处理的。
public class Emp implements Weather{
String name;
public Emp(String name) {
this.name = name;
}
//人是要根据天气做出相应的处理的。 "晴天","雾霾","刮风","冰雹","下雪"
public void notifyWeather(String weather){
if("晴天".equals(weather)){
System.out.println(name+"高高兴兴的去上班!!");
}else if("雾霾".equals(weather)){
System.out.println(name+"戴着消毒面具去上班!");
}else if("刮风".equals(weather)){
System.out.println(name+"拖着大石头过来上班!");
}else if("冰雹".equals(weather)){
System.out.println(name+"戴着头盔过来上班!");
}else if("下雪".equals(weather)){
System.out.println(name+"戴着被子过来上班!");
}
}
}
气象站类:
//气象站
public class WeatherStation {
String[] weathers = {"晴天","雾霾","刮风","冰雹","下雪"};
//当前天气
String weather ;
//该集合中存储的都是需要收听天气预报的人
ArrayList<Weather> list = new ArrayList<Weather>(); //程序设计讲究低耦合---->尽量不要让一个类过分依赖于另外一个类。
public void addListener(Weather e){
list.add(e);
}
//开始工作
public void startWork() {
final Random random = new Random();
new Thread(){
@Override
public void run() {
while(true){
updateWeather(); // 每1~1.5秒更新一次天气 1000~1500
for(Weather e : list){
e.notifyWeather(weather);
}
int s = random.nextInt(501)+1000; // 500
try {
Thread.sleep(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
//更新天气的 方法
public void updateWeather(){
Random random = new Random();
int index = random.nextInt(weathers.length);
weather = weathers[index];
System.out.println("当前的天气是: " + weather);
}
}
主类运行:
public class WeatherMain {
public static void main(String[] args) throws Exception {
//工人
Emp e = new Emp("小明");
Emp e2 = new Emp("如花");
//学生
Student s1 = new Student("狗娃");
Student s2 = new Student("狗剩");
WeatherStation station = new WeatherStation();
station.addListener(e);
station.addListener(e2);
station.addListener(s1);
station.addListener(s2);
station.startWork();
}
}
观察者设计模式的步骤总结:
1. 当前目前对象发生指定的动作是,要通知另外一个对象做出相应的处理,这时候应该把对方的相应处理方法定义在接口上。
2. 在当前对象维护接口的引用,当当前对象发生指定的动作这时候即可调用接口中的方法了。
使用观察者模式解决问题从而降低程序耦合度