面向对象程序设计(OOP设计模式)-行为型模式之观察者模式的应用与实现

课程名称:程序设计方法学

实验5:OOP设计模式-行为型模式的应用与实现

时间:2015年12月02日三,第3、4节地点:理1

一、实验目的

加深对行为型设计模式的理解以及在开发中的实际应用能力。

二、实验内容

实验内容:

在工业自动化系统中,作为监控端,要求能够实时采集生产线上每一个测点的数据,并根据事先设定好的条件来发出告警。目前,系统可以支持的告警方式在形式上呈现多样化的趋势,主要包括屏幕显示告警、语音发声告警、电话拨号告警、电子邮件告警、手机短信告警以及其他可利用的告警方式等。在设置监控端时,用户可以根据实际需要,针对生产线上的每个测点,动态地设定与其相关联的多个告警。每个告警都有对应的告警方式和告警对象。当从某个测点返回的采集数据超过了事先设定好的阈值时,就要立即触发与该测点相关的所有告警,以便相关人员能够及时得到有关异常情况的通知,便于其进行人工干预和处理。

针对以上说明,现在要求你设计监控端软件中的告警功能部分。要求使该系统能够实现针对测点和告警间的一对多的动态组合,并具有较强的可扩展性。

要求:

实验报告中要求绘制UML类图,给出设计中各个类的主要成员,并附以适当的文字说明详细描述每个类的作用;

实验报告中应针对上述设计,给出使用C++(或java)实现的完整的示意性代码,以及在本地计算机上调试、运行该程序的截图(要求截图的结果中能体现个人的学号、姓名等信息)。

实验报告的末尾请对所用的设计模式、该模式的优缺点及使用心得等做简要小结。

附加要求:

对于我们所介绍的常见的几种行为型的设计模式,你能不能也举出这些模式的一些应用实例,并给出相关的UML类图说明呢?

三、实验环境

硬件条件:微机

操作系统:Windows 2007

开发环境:Eclipse,Rational Rose 2003

四、实验步骤和结果

(一)选择适当的面向对象设计模式

由题意,要求设计一个设计监控端软件中的告警功能,作为监控端,要求能够实时采集生产线上每一个测点的数据,并根据事先设定好的条件来发出告警。告警方式有多样,当从某个测点返回的采集数据超过了事先设定好的阈值时,就要立即触发与该测点相关的所有告警。这需要实现测点和告警间的一对多的动态组合。故选用的是行为型设计模式中的观察者模式。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己,并做出相应动作。

(二)UML类图的设计和绘制

设计分析:

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,所有依赖于它的对象都得到通知并被自动更新。观察者模式中的角色有:

1、 抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。

2、 具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。

3、 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。

4、 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。


(图1 一般的观察者模式的UML类图 )


(图2该监控端软件中的告警功能的观察者模式的UML类图)

(三)针对上述设计,用java实现的完整的示意性代码如下所示:

Java 类的建立如下所示:


1、Sub_MeasuringPoint抽象类,即测点抽象类,该目标抽象类提供注册和删除观察者对象的接口:


package com.shen.observer;

import java.util.ArrayList;

//目标类:

//目标知道它的观察者,可以有任意多个观察者观察同一目标

//提供注册和删除观察者对象的接口

public abstract class Sub_MeasuringPoint {

//用来保存注册的观察者对象

private ArrayList <Observer> list=new ArrayList<Observer>();

//注册观察者对象

public void Attach(Observer observer) {

list.add(observer);

System.out.println("Attached an observer successfully!");

}

//删除观察者对象

public void Detach(Observer observer) {

list.remove(observer);

System.out.println("Detached an observer successfully!");

}

//通知所有注册的观察者对象

public void NotifyObservers(String newState) {

for (Observer observer:list) {

observer.Update(newState);

observer.AlarmMode();

}

}

}

2、ConSub_MeasuringPoint具体目标类,当从某个测点返回的采集数据超过了事先设定好的阈值时,就要立即触发与该测点相关的所有告警


package com.shen.observer;

//具体目标类

public class ConSub_MeasuringPoint extends Sub_MeasuringPoint {

private String state;

public String getState() {

return state;

}

//当从某个测点返回的采集数据超过了事先设定好的阈值时,就要立即触发与该测点相关的所有告警,

//数据超过阈值

public void DataOverThreshold(String newState) {

state=newState;

System.out.println(">>>>>当前检测到测点状态为:"+state);

////状态发生改变,通知各个观察者

this.NotifyObservers(state);

}

}

3、Observer 观察者接口,为那些在目标发生时需获得通知的对象定义一个更新接口:


package com.shen.observer;

//这是一个观察者接口,为那些在目标发生时需获得通知的对象定义一个更新接口

public interface Observer {

public void Update(String state);//检查到的状态更新

public Object alarmObject=new Object();//告警对象

public void AlarmMode();//告警方式

}

4、Ob_ScreenDisplayAlarm 屏幕显示告警:


package com.shen.observer;

//屏幕显示告警

public class Ob_ScreenDisplayAlarm  implements Observer{

//观察者的状态

@SuppressWarnings("unused")

private String  observerState;

@Override

public void Update(String state) {

// TODO Auto-generated method stub

observerState=state;

System.out.print("[屏幕显示告警器]发现测点数据超过阈值");

}

@Override

public void AlarmMode() {

// TODO Auto-generated method stub

System.out.println(",于是触发【屏幕显示告警】!");

}

}

5、Ob_VoiceAudibleAlarm语音发声告警:


package com.shen.observer;

//语音发声告警

public class Ob_VoiceAudibleAlarm implements Observer{

//观察者的状态

@SuppressWarnings("unused")

private String  observerState;

@Override

public void Update(String state) {

// TODO Auto-generated method stub

observerState=state;

System.out.print("[语音发声告警器]发现测点数据超过阈值");

}

@Override

public void AlarmMode() {

// TODO Auto-generated method stub

System.out.println(",于是触发【语音发声告警】!");

}

}

6、Ob_TelephoneDialingAlarm电话拨号告警:


package com.shen.observer;

//电话拨号告警

public class Ob_TelephoneDialingAlarm implements Observer{

//观察者的状态

@SuppressWarnings("unused")

private String  observerState;

@Override

public void Update(String state) {

// TODO Auto-generated method stub

observerState=state;

System.out.print("[电话拨号告警器]发现测点数据超过阈值");

}

@Override

public void AlarmMode() {

// TODO Auto-generated method stub

System.out.println(",于是触发【电话拨号告警】!");

}

}

7、Ob_EmailAlarm 电子邮件告警


package com.shen.observer;

//电子邮件告警

public class Ob_EmailAlarm implements Observer {

//观察者的状态

@SuppressWarnings("unused")

private String  observerState;

@Override

public void Update(String state) {

// TODO Auto-generated method stub

observerState=state;

System.out.print("[电子邮件告警器]发现测点数据超过阈值");

}

@Override

public void AlarmMode() {

// TODO Auto-generated method stub

System.out.println(",于是触发【电子邮件告警】!");

}

}

8、Ob_SMSAlarm 手机短信告警


package com.shen.observer;

//手机短信告警

public class Ob_SMSAlarm implements Observer{

//观察者的状态

@SuppressWarnings("unused")

private String  observerState;

@Override

public void Update(String state) {

// TODO Auto-generated method stub

observerState=state;

System.out.print("[手机短信告警器]发现测点数据超过阈值");

}

@Override

public void AlarmMode() {

// TODO Auto-generated method stub

System.out.println(",于是触发【手机短信告警】!");

}

}

9、Ob_OtherAvailableAlarm其他可利用的告警方式


package com.shen.observer;

//其他可利用的告警方式

public class Ob_OtherAvailableAlarm implements Observer{

//观察者的状态

@SuppressWarnings("unused")

private String  observerState;

@Override

public void Update(String state) {

// TODO Auto-generated method stub

observerState=state;

System.out.print("[其他可利用的告警方式]发现测点数据超过阈值");

}

@Override

public void AlarmMode() {

// TODO Auto-generated method stub

System.out.println(",于是触发其他可利用的告警方式......");

}

}

(四)编写监控器测试代码(MonitorClientTest.java)如下所示:


package com.shen.observer;

//客户端测试类

public class MonitorClientTest {

public static void main(String[] args) {

// 创建主题对象,即测点

System.out.println("--------<监控端软件中的告警功能_(105032013120沈晓麟)>-------");

ConSub_MeasuringPoint measuringPoint=new ConSub_MeasuringPoint();

//创建屏幕显示告警观察者对象

Observer observer1=new Ob_ScreenDisplayAlarm();

//创建语音发声告警观察者对象

Observer observer2=new Ob_VoiceAudibleAlarm();

//创建电话拨号告警观察者对象

Observer observer3=new Ob_TelephoneDialingAlarm();

//创建电子邮件告警观察者对象

Observer observer4=new Ob_EmailAlarm();

//创建手机短信告警观察者对象

Observer observer5=new Ob_SMSAlarm();

//创建其他可利用的告警方式观察者对象

Observer observer6=new Ob_OtherAvailableAlarm();

//将观察者对象注册到主题对象上

measuringPoint.Attach(observer1);

measuringPoint.Attach(observer2);

measuringPoint.Attach(observer3);

measuringPoint.Attach(observer4);

measuringPoint.Attach(observer5);

measuringPoint.Attach(observer6);

//改变主题对象的状态

measuringPoint.DataOverThreshold("测点返回的采集数据超过阈值!!!");

}

}

调试程序,运行结果如图所示:


五、实验结果和讨论

在编写完相应代码及测试程序后,调试程序,运行结果如图所示:


六、总结

(一)本次实验按时按量完成。通过实验基本掌握了行为型设计模式中的观察者模式。

(二)本次实验使用的是观察者模式。观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 在观察者模式中,一个目标物件(被观察者)管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知,这通常通过呼叫各观察者所提供的方法来实现。

优点:

1. 目标和观察者对象之间的抽象耦合。一个目标所知道的仅仅是它有一系列观察者,每个都符合抽象的Observer类的简单接口。目标不知道任何一个观察者属于哪一个具体的类,它只知道它们都有一个共同的接口。这样目标和观察者之间的耦合是抽象的和最小的。

2. 支持广播通信。不像通常的请求,目标发送的通知不需指定它的接收者。通知被自动广播给所有已向该对象登记的有关对象。

缺点:

1. 意外的更新。因为一个观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

2. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

3. 果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

4.如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

(三)使用观察者模式的心得体会:

从GOF给出的Observer模式的意图:“定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新”。中,我们可以得到两个信息,如下:

1.观察者(具体执行操作的对象,有多个)

2.被观察者(顾名思义是被观察的对象,如果该对象发生某些变化则通知观察者执行对应的操作。)

目标Suject提供依赖于它的观察者Observer的注册(Attach)和注销(Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作(Notify)。

观察者则提供一个Update操作,需要注意的是这里的Observer的Update操作并不在Observer改变了Subject目标状态的时候就对自己进行更新,这个更新操作要延迟到Subject对象发出Notify通知所有Observer进行修改(调用Update)。

通过学习,我了解到Observer是影响极为深远的模式之一,也是在大型系统开发过程中要用到的模式之一。

七、附加要求

对于我们所介绍的常见的几种结构型的设计模式,举出这些模式的一些应用实例,并给出相关的UML类图说明。

此处以“学生逐级请假制度”举例如下:

大学学生有事情离开学校需要请假,请假1天,辅导员可以批准;请假2天,学院副书记可以批准;请假超过2天,则需要找学院院长批假!

此处则采用职责链模式来实现上述制度。

职责链模式是一种对象的行为模式。在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象 决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。

职责链模式的组成:
    1、抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对后继者的引用。这个角色通常由一个抽象类或接口实现。
    2、具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问后继者。

3、客户端测试(ClientTest)角色:向职责链上的具体处理者(ConcreteHandler)对象提交请求。

UML类图设计如下所示:


(一) 代码设计如下所示:

1、处理请假请求的接口


package com.shen.cor;

//处理请假请求的接口

public abstract class LeaveBaseHandler {

//后继者

protected LeaveBaseHandler successor;

//get 和set 方法

public LeaveBaseHandler getSuccessor() {

return successor;

}

public void setSuccessor(LeaveBaseHandler successor) {

this.successor = successor;

}

//处理请假请求的方法

public  abstract void requestLeave(int days);

}

2、对请假一天的处理


package com.shen.cor;

//对请假一天的处理

public class OnedayLeaveConcreteHandler extends LeaveBaseHandler {

@Override

public void  requestLeave(int days) {

if (days<=1) {

System.out.println(">>>辅导员可以批准请假1天");

}

else {

super.successor.requestLeave(days);

}

}

}

3、对请假两天的处理


package com.shen.cor;

//对请假两天的处理

public class TwodaysLeaveConcreteHandler extends LeaveBaseHandler {

@Override

public void requestLeave(int days) {

if (days>1&&days<=2) {

System.out.println(">>>学院副书记可以批准请假2天");

}

else {

super.successor.requestLeave(days);

}

}

}

4、客户端测试类:


package com.shen.cor;

//客户端测试类

public class ClientTest {

private static void requestLeave() {

LeaveBaseHandler oneDay=new OnedayLeaveConcreteHandler();

LeaveBaseHandler twoDays=new TwodaysLeaveConcreteHandler();

LeaveBaseHandler moreThanTwoDays=new MoreThanTwodaysConcreteHandler();

oneDay.setSuccessor(twoDays);

twoDays.setSuccessor(moreThanTwoDays);

oneDay.requestLeave(1);

oneDay.requestLeave(2);

oneDay.requestLeave(3);

}

public static void main(String[] args) {

System.out.println("----------通过职责链模式实现逐级请假制度_105032013120----------");

requestLeave();

}

}

(二) 测试结果如下所示:


时间: 2024-10-06 18:14:56

面向对象程序设计(OOP设计模式)-行为型模式之观察者模式的应用与实现的相关文章

设计模式-行为型模式,观察者模式(13)

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern).比如,当一个对象被修改时,则会自动通知它的依赖对象.观察者模式属于行为型模式. 有时,我们希望在一个对象的状态改变时更新另外一组对象. class Publisher: def __init__(self): self.observers = [] def add(self, observer): if observer not in self.observers: self.observers.append(obs

设计模式----行为型模式之观察者模式(Observer Pattern)

下面是阅读<Head First设计模式>的笔记. 观察者模式 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. JDK API内置机制 JDK1.0版本就已经包含了java.util.Observer和java.util.Observable,TODO. java.util.Observer是一个接口,所有使用内置机制实现观察者模式,都需要实现该接口.该接口只定义了一个方法 void update(Observable o, Object a

JDK 源码 阅读 - 2 - 设计模式 - 创建型模式

A.创建型模式 抽象工厂(Abstract Factory) javax.xml.parsers.DocumentBuilderFactory DocumentBuilderFactory通过FactoryFinder实例化具体的Factory. 使用例子: DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilder

设计模式——创建型模式

简单的说我们可以把23种设计模式可以归为三大类,分别是创建型模式.结构型模式和行为型模式. 今天,首先看一下创建型模式.创建型设计模式包括5种:单例模式(Singleton).工厂方法模式(Factory Method).抽象工厂模式(Abstract Factory).建造者模式(Builder).原型模式(Prototype).  1.单例模式(Singleton)        1)简介 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的软件设计模式.在它的核心结

设计模式06-原型模式

1. 概念 用原型的实例指定创建对象的种类,并且通过拷贝这些原型对象来创建新的对象   在java中直接实现Cloneable接口即可 2. 案例 /********************************************************************** * <pre> * FILE : PrototypeDemo.java * CLASS : PrototypeDemo * * AUTHOR : Liaokailin * * FUNCTION : TODO

C#设计模式-创建型模式(转)

一.简单工厂模式 简单工厂模式Simple Factory,又称静态工厂方法模式.它是类的创建模式.是由一个工厂对象决定创建出哪一种产品类的实例,是不同的工厂方法模式的一个特殊实现. 优点: u 模式的核心是工厂类,该类中含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅负责"消费"产品. u 简单工厂模式实现了对责任的分割. 缺点: u 当产品类有复杂的多层次等级结构时,工厂类只有它自己.以不变应万变. u 模式中工厂类集中了所

【C#设计模式——创建型模式】抽象工厂模式

抽象工厂模式比工厂模式具有更高层次的抽象性.当要返回一系列相关类中的某一个,而每个类都能根据需要返回不同的对象时,可以选择这种模式.直接进入示例. 示例描述:完成花园的规划,多种花园种类,每个里面多种植物 编写一个基类Garden,Garden就是抽象工厂.它定义了具体类中的方法,并返回一系列相关类中的某个类. public class Garden { protected Plant center, shade, border; protected bool showCenter, showS

设计模式——行为型模式

继<设计模式--创建型模式>和<设计模式--结构型模式>之后,今天介绍一下行为型模式. 行为模式设计到算法和对象间的职责分配,不仅描述对象或类的模式,还描述他们之间的通信方式,客服了运行时难以跟踪的复杂的控制流,他们将你的注意力重控制流转移到对象间的关系上来.行为类模式采用继承机制在类间分派行为,例:模板方法模式.解释器模式:行为对象模式描述了一组相互对等的对象如何相互协作以完成其中任何一个对象都单独无法完成的任务,例:中介者模式.职责链模式.策略模式:其它的行为对象模式常将行为封

java设计模式--行为型模式--迭代模式

1 迭代器模式 2 概述 3 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 4 5 6 适用性 7 1.访问一个聚合对象的内容而无需暴露它的内部表示. 8 9 2.支持对聚合对象的多种遍历. 10 11 3.为遍历不同的聚合结构提供一个统一的接口(即,支持多态迭代). 12 13 14 参与者 15 1.Iterator 16 迭代器定义访问和遍历元素的接口. 17 18 2.ConcreteIterator 19 具体迭代器实现迭代器接口.

java设计模式--行为型模式--命令模式

1 命令模式 2 概述 3 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作. 4 5 6 适用性 7 1.抽象出待执行的动作以参数化某对象. 8 9 2.在不同的时刻指定.排列和执行请求. 10 11 3.支持取消操作. 12 13 4.支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍. 14 15 5.用构建在原语操作上的高层操作构造一个系统. 16 17 18 参与者 19 1.Command 20 声明执行操作的接口.