当前位置: 首页 > news >正文 资料网站怎么做的网站建设的技术有哪些 news 2025/10/27 7:21:45 资料网站怎么做的,网站建设的技术有哪些,上海广告公司电话,如何创建网站后台. 基本概念 观察者#xff08;Observer#xff09;模式中包含两种对象#xff0c;分别是目标对象和观察者对象。在目标对象和观察者对象间存在着一种一对多的对应关系#xff0c;当这个目标对象的状态发生变化时#xff0c;所有依赖于它的观察者对象都会得到通知并执行它…. 基本概念 观察者Observer模式中包含两种对象分别是目标对象和观察者对象。在目标对象和观察者对象间存在着一种一对多的对应关系当这个目标对象的状态发生变化时所有依赖于它的观察者对象都会得到通知并执行它们各自特有的行为。 通俗地说就好像这些观察者对象在时刻注视着目标对象被观察。无论何时该目标对象的状态发生变化这些观察者对象都能够马上知道并根据目标对象的新状态执行相应的任务。 观察者模式又叫发布-订阅Publish-Subscribe模式其中的订阅表示这些观察者对象需要向目标对象进行注册这样目标对象才知道有哪些对象在观察它。发布指的是当目标对象的状态改变时它就向它所有的观察者对象发布状态更改的消息以让这些观察者对象知晓。 一个目标对象的观察者对象数量是不固定的可以随时增加新的观察者对象或取消已有的观察者对象。观察者模式的主要优点就是极大地降低了目标对象和观察者对象间的耦合二者可以独自地改变和复用让对系统增加功能或删除功能都很方便。 2. 应用举例 我们举一个实际的例子来说明对观察者模式的运用假设我们有一个天气App它有很多个界面组件这些组件的作用分别是显示摄氏温度、显示华氏温度、显示气温感受比如炎热、凉爽和寒冷等等。当然该App应该还有另一个对象用于获取实时的天气数据我们称它为天气对象。 这个天气对象和界面组件之间的依赖关系就可以用观察者模式实现该天气对象就是目标对象天气数据就是它的状态。这些界面组件就是观察者对象当天气对象获取到新的天气数据时此时它的状态改变了它就通知所有依赖于它的界面组件这些组件就更新它们显示的内容。 图2 天气App中的观察者模式 现在我们想扩展这个天气App的功能让它可以向用户建议如何穿衣。因此我们需要一个新的界面组件当温度高时显示穿薄点当温度低时显示穿羽绒服。我们让这个新的界面组件注册成为天气对象目标对象的观察者这样当天气数据改变时它就会自动得到通知并显示新的穿衣建议。而天气对象和其余的界面组件都不会受到影响也无需改变。 现在让我们再次修改这个天气App这次是要删除显示华氏温度的功能。因为我们中国人更习惯摄氏温度显示华氏温度不但多此一举还可能让用户误将它当作摄氏温度。此时我们只需向天气对象目标对象取消注册该界面组件再删除它就可以了天气对象在数据更新时就不会再通知该界面组件了。同样的该App的其余部分也不会受到本次修改的影响。 3. 结构 我们先直接给出观察者模式的类结构图以及这些类充当的角色和作用再解释为什么它们是这样的结构。 图3 观察者模式的类结构图 Subject目标类它是一个抽象类也是所有目标对象的父类。它用一个列表记录当前目标对象有哪些观察者对象并提供增加、删除观察者对象和通知观察者对象的接口。 Observer观察者类它也是一个抽象类是所有观察者对象的父类它为所有的观察者对象都定义了一个名为update的方法也叫成员函数。当目标对象的状态改变时它就是通过调用它的所有观察者对象的update方法来通知它们的。 ConcreteSubject具体目标类可以有多个不同的具体目标类它们同时继承Subject类。一个目标对象就是某个具体目标类的对象一个具体目标类负责定义它自身的事务逻辑并在状态改变时通知它的所有观察者对象。 ConcreteObserver具体观察者类可以有多个不同的具体观察者类它们同时继承Observer类。一个观察者对象就是某个具体观察者类的对象。每个具体观察者类都要重定义Observer类中定义的update方法在该方法中实现它自己的任务逻辑当它被通知的时候目标对象调用它的update方法就执行自己特有的任务。 注意在Java语言中Observer类可以用接口interface代替此时所有的具体观察者类都要实现该接口。 3.1 Observer和ConcreteObserver 首先目标对象需要知道有哪些观察者对象在观察它这样它才知道状态改变时应该通知哪些观察者对象并且它还要能随时添加和删除观察者对象。所以目标对象应该要有一个列表来保存对它的所有观察者对象的引用。但在C或Java这样的编程语言中一个列表中的所有项都必须是同一类型的。这说明所有的观察者对象都必须是同一个类但这样会限制程序的灵活性。因为不同的观察者对象要执行不同的任务我们应该让它们属于不同的类。解决这一矛盾的途径是让所有的观察者类都有一个共同的父类Observer这些观察者类ConcreteObserver都是该父类的不同子类。因为所有子类的对象都可以被当作父类的对象因此它们即可以保持不同又可以保存在同一列表中。 同时这也解决了另一个问题那就是目标对象是如何通知它的观察者对象的呢当然这是通过调用它的观察者对象的一个方法也叫成员函数来实现的。目标对象只需要负责通知它的观察者对象它的状态改变了而对该观察者对象如何处理新状态以及属于哪个具体观察者类都不需要了解。这就是说目标对象只能以同一种方式对待它的所有观察者对象即这些观察者对象都要有一个相同的方法供目标对象调用我们称该方法为update方法。 我们在抽象观察者类Observer中定义该方法并在所有具体观察者类ConcreteObserver中重定义它。当目标对象的状态改变时它在它的列表中每遍历到一个观察者对象就调用该观察者对象的update方法。对目标对象来说所有的观察者对象都是Observer类的并且该类确实有一个update方法所以能调用成功。又因为多态实际执行的却是该观察者对象所属的具体观察者类中重定义的那个update方法。 要在观察者类中建立这样的继承关系的另一大原因是为了能方便地扩展功能。因为目标对象将所有的观察者对象都当作Observer类的对象来处理所以要增加某种新的观察者对象时我们只需创建一个新的类让它继承Observer类并重定义update方法在该update方法中实现它自己的任务逻辑就行了。这样所有由该新类创建的观察者对象都可以很容易地融入到当前的观察者模式中程序的其余部分都不需要改变。 3.2 Subject和ConcreteSubject 那么为什么目标类目标对象所属的类也需要有一个抽象目标类Subject和多个具体目标类ConcreteSubject这样的继承结构呢如果整个系统中只有一个目标对象那么确实可以只用一个目标类实现观察者模式。我们之前说的都是多个观察者对象观察一个目标对象但其实一个观察者对象也可以同时观察多个目标对象。 既然要同时观察多个目标对象那么它们很可能有不同的状态以及不同的功能即这些目标对象可能属于不同的类。也就是说一个观察者对象要被多个不同类的目标对象通知到注意目标对象通知观察者对象是通过调用观察者对象的一个方法实现的。我们先考虑一个笨办法在观察者类中为每一个目标类都提供一个版本的update方法。这样不仅麻烦而且代码难以维护想象一下我们要增加一个新的目标类那么就需要在所有要观察它的观察者类中都增加一个对应版本的update方法当我们想删掉一个目标类的时候又要在这些观察者类中删除那个对应版本的update方法。 一个通用的解决方式是让所有的目标类都调用同一个update方法但是将自身的引用作为该方法的一个参数传递给观察者对象这样观察者对象就知道是哪一个目标对象在通知它。一个方法或成员函数的参数的类型是确定的也就是说所有的目标类都应该是同一个类。 这就又出现了观察者类中开始的矛盾局面即所有的目标类既要是同一个类也要是不同的类。解决的方式也是一样的即所有的目标类都有同一个父类抽象目标类Subject而不同的目标类具体目标类ConcreteSubject都是该父类的不同子类。 无论一个观察者对象可以同时观察多个目标对象还是只能观察一个目标对象目标类的这种继承关系都有助于增加新的目标类即扩展程序的功能。当我们想增加新的具体目标类时就创建一个新类再让它继承Subject类并实现它自己特有的事务逻辑就可以了。这样由该新类所创建的目标对象就可以很轻松地融入到当前的观察者模式中程序的其余部分都不会受到影响。 抽象目标类Subject和具体目标类ConcreteSubject以及抽象观察者类Observer和具体观察者类ConcreteObserver之间的继承关系降低了目标对象它属于某个具体目标类和观察者对象它属于某个具体观察者类之间的耦合度。 3.3 获取新状态 总的来说有两种方式可以让观察者对象获取到目标对象的新状态。一是当目标对象调用每个观察者对象的update方法时将代表它新状态的数据作为该update方法的一个参数传递给该观察者对象。二是目标对象在调用update方法时并不传递新状态而是该观察者对象在被通知到的时候在update方法中再主动去询问该目标对象的新状态是什么。 如果采用第二种方式那么观察者对象需要拥有它的目标对象的引用再通过该引用调用目标对象的某个方法该方法返回目标对象的新状态。该引用可能是目标对象调用观察者对象的update方法时传递来的也可能是最初将该观察者对象添加进目标对象的列表中订阅的时候设置该观察者对象的某个成员变量让它一直保存对该目标对象的引用。 此时我们可能又要面对既要相同又要不同的问题。先考虑目标对象在调用观察者对象的update方法时传递回它的新状态的方式我们已知update方法的原型是唯一的即它的参数数量和类型以及返回值类型是确定了的。既然所有具体目标类的状态都要作为同一个参数传递那么这些状态都必须是同一种类型的。但是这些不同的具体目标类的状态很可能不一样至少在某些细节上有差异这样看的话它们的状态又很可能是不同类型的。 再考虑上面的第二种方式即观察者对象在获得通知后再调用目标对象的某个方法该方法返回目标对象的新状态。我们纠结的是如何在所有的目标类中实现这个状态获取方法我们称它为getState方法。 3.3.1 用继承方式实现状态获取方法 首先我们可以在目标类的继承关系中实现getState方法也就是先在抽象目标类Subject中定义一个getState方法然后再在每个具体目标类中重定义该getState方法使之返回该具体目标类的实际状态。这样做是很容易想到的因为所有的具体目标类都要有一个功能相似的getState方法而所有目标类本身就有一个建立好的继承关系。对于所有子类中相似的部分我们应该将它提取到父类中让子类继承以实现一致性。 另一个原因是当一个观察者对象同时观察多个目标对象时这些目标对象都是作为Subject类的对象通过update方法传递给它的。观察者对象将通知它的目标对象都当作Subject类型的对象对待的可能根本就不知道该目标对象到底属于哪个具体目标类。此时也要求在Subject父类中为所有类型的目标对象都定义一个相同的状态获取方法。 此时getState方法的实现和update方法是相似的都是利用了多态的特性让调用父类对象的方法时实际执行的是该对象真正所属的子类中重定义的同名方法。这种实现getState方法的措施限制了getState方法的原型也是唯一的即它的参数数量和类型以及返回值类型都是确定了的也就要求所有具体目标类的状态是同一种类型的。 如果所有具体目标类的状态确实是同一种类型或者可以提炼到同一种类中那么以上两种获取目标对象新状态的方式都是可行的。同时为了保持各个具体目标类的状态的差异化状态的实现也可以采用继承的方式。定义一个抽象状态类和多个具体状态类所有具体状态类继承该抽象状态类。每个具体目标类将它对应的具体状态类的对象代表该具体目标类的状态作为抽象状态类的对象通过update方法传递给观察者对象或者通过getState方法返回给它们。 3.3.2 每个具体目标类实现不同的状态获取方法 然而现实中也有很多这样的情况那就是多个具体目标类的状态之间差异太大根本无法统一为同一种类型。此时只能使用第二种获取目标对象新状态的方式因为这些不同具体目标类的状态根本不能作为update方法的同一个参数进行传递。 因此各个具体目标类的状态获取方法也会是不一样的至少它们的返回值类型是不一样的很可能连方法名也不相同。这样就无法在抽象目标类Subject中为所有的具体目标类定义相同的getState方法。 当观察者对象被它的目标对象通知状态改变时它必须要知道该目标对象是什么具体目标类的这样它才能调用该具体目标类专有的状态获取方法来获取新状态。但是前文已多次说过所有目标对象都是作为Subject类型传递给观察者对象的这似乎又是矛盾的。 其实这个问题也可以解决虽然确实是任意一种具体目标类的目标对象都可以调用任意一个观察者对象的update方法但实际上一个观察者对象只对某些具体目标类的目标对象感兴趣。因为它需要特定类型的输入数据而不是任何数据它都可以处理。比如第2小节中我们那个天气App的例子中的所有观察者对象界面组件都只能处理天气数据而对金融或交通数据都不适用。 通常在设计一个具体观察者类的时候就已知它所期待的目标对象是属于哪一些具体目标类的我们也应该只让该类的观察者对象订阅它所期待的那些类的目标对象。当观察者对象的update方法被调用时它可以检测传递进来的目标对象是否属于它所期待的那些具体目标类比如Java中的instanceof运算符就可以检测一个对象是否是某种类的对象。如果不是那么它就忽略本次通知而什么也不做如果是它就知道了该目标对象的具体类型也就能调用该目标对象专有的状态获取方法了。 这样做看似会降低该具体观察者类的复用性但实际情况是每一个具体观察者类都不是要在任意场景中都可以使用它本身就是只针对某一领域设计的。上面的观察者模式类图中以及下面我们实现观察者模式的时候就是用这种方式获取目标对象的新状态的。 4. 实现 现在让我们来用Java语言和观察者模式实现第2小节中的那个天气App的例子当然我们不会真的去开发一个功能完整且界面美观的App我们让这些界面组件打印出它们应该显示的内容来模拟它们的实际功能。 首先在Observer.java文件中我们定义抽象目标类Subject和接口MyObserver接口MyObserver充当观察者模式类图结构中的抽象观察者类Observer我们之前就说过这个抽象父类可以用接口实现。 另一个要注意的是我们将该接口命名为MyObserver而不是Observer这是因为Java中本来就有一个自带的名为Observer的接口它也是用来实现观察者模式的。这里我们想完全实现我们自己的观察者模式而不使用Java自带的Observer接口。 MyObserver接口只有一个方法update目标对象通过调用它来通知观察者对象它的状态改变了该update方法有一个类型为Subject的参数这允许目标对象将它自己传递给观察者对象这样一个观察者对象就可以同时观察多个目标对象。 在这个简单例子中只有一个目标对象因此也只有一个具体目标类它就是Weather类。为了例子保持简单这里的天气数据只包含温度Weather类的状态就是当前的温度值它通过随机生成一个-80至60的浮点数作为新的温度值来模拟对天气数据的获取当然实际中的App应该通过一个接口到服务器上获取真实的气象数据。 目标对象必须确保状态确实改变了才通知观察者对象因此Weather类必须测试新的温度值是否和之前的温度值相等。Weather类的状态获取方法getTemperature是它特有的没有按照继承关系的方式定义它即其它具体目标类的状态获取方法是不同的。 在这个例子中目标对象的状态改变时由它自己调用它的notifyObservers方法通知所有的观察者对象notifyObservers方法会依次调用每个观察者对象的update方法。其实也可以在目标对象的状态改变后由客户代码调用目标对象的notifyObservers方法通知观察者。 在ui.java文件中我们定义两个界面组件类CelsiusView和WearView它们都是具体观察者类因此它们都要实现MyObserver接口。CelsiusView按照摄氏度显示温度值而WearView则显示穿衣建议。当然这个例子中它们并不会绘制实际的界面而是通过一个打印语句来模拟对界面的显示。 虽然我们说过一个观察者对象可以同时观察多个属于不同类的目标对象但在该例子中的观察者对象只会观察一个目标对象因为这两个界面组件是用于显示天气信息的因此对其它类型的目标对象也不感兴趣。所以当它们被目标对象通知的时候它们会在检查目标对象确实是一个Weather类的对象后才执行各自的任务。 当这两个观察者对象确实收到来自Weather类的目标对象的通知时它们就将该目标对象强制转换为Weather类的对象并通过调用Weather类的专有状态获取方法getTemperature()获取目标对象的新状态。 在App.java文件中我们定义App类它模拟该天气App的运行。以上示例代码的执行结果如下图所示我们可以看到当目标对象的状态改变时在本例子中是温度值的改变两个观察者对象都被通知到了并更新了它们的界面显示。 图4 示例代码的执行结果 5. 结语 在某些平台上可以向目标对象同时注册一个观察者对象和它的某个方法成员函数。这样当目标对象的状态改变时它就调用这个观察者对象的这个注册的方法而不一定要去调用它的update方法。这就允许这些观察者对象没有update方法即它们不用都继承自同一个父类。当然一个目标对象可能要求它的所有观察者注册的回调方法都具有相同的函数原型即这些方法要有相同数量和类型的参数以及相同类型的返回值。 观察者模式还有很多其它的实现方式但这些方式都只是在一些细节上有所不同。只要理解了观察者模式的主要概念就能够很容易理解这些细节差异。 文章转载自: http://www.morning.xplng.cn.gov.cn.xplng.cn http://www.morning.wgtnz.cn.gov.cn.wgtnz.cn http://www.morning.lblsx.cn.gov.cn.lblsx.cn http://www.morning.tpnx.cn.gov.cn.tpnx.cn http://www.morning.wwnb.cn.gov.cn.wwnb.cn http://www.morning.spkw.cn.gov.cn.spkw.cn http://www.morning.lynb.cn.gov.cn.lynb.cn http://www.morning.ssgqc.cn.gov.cn.ssgqc.cn http://www.morning.zrdqz.cn.gov.cn.zrdqz.cn http://www.morning.kzslk.cn.gov.cn.kzslk.cn http://www.morning.bpmtg.cn.gov.cn.bpmtg.cn http://www.morning.myhpj.cn.gov.cn.myhpj.cn http://www.morning.sskns.cn.gov.cn.sskns.cn http://www.morning.jlgjn.cn.gov.cn.jlgjn.cn http://www.morning.ljqd.cn.gov.cn.ljqd.cn http://www.morning.nccqs.cn.gov.cn.nccqs.cn http://www.morning.plqqp.cn.gov.cn.plqqp.cn http://www.morning.jkszt.cn.gov.cn.jkszt.cn http://www.morning.rrjzp.cn.gov.cn.rrjzp.cn http://www.morning.iuibhkd.cn.gov.cn.iuibhkd.cn http://www.morning.mrpqg.cn.gov.cn.mrpqg.cn http://www.morning.clybn.cn.gov.cn.clybn.cn http://www.morning.nwljj.cn.gov.cn.nwljj.cn http://www.morning.bpmnx.cn.gov.cn.bpmnx.cn http://www.morning.jbtzx.cn.gov.cn.jbtzx.cn http://www.morning.yhxhq.cn.gov.cn.yhxhq.cn http://www.morning.gmysq.cn.gov.cn.gmysq.cn http://www.morning.dndjx.cn.gov.cn.dndjx.cn http://www.morning.hflrz.cn.gov.cn.hflrz.cn http://www.morning.tscsd.cn.gov.cn.tscsd.cn http://www.morning.dbfj.cn.gov.cn.dbfj.cn http://www.morning.cbqqz.cn.gov.cn.cbqqz.cn http://www.morning.kpcxj.cn.gov.cn.kpcxj.cn http://www.morning.dpnhs.cn.gov.cn.dpnhs.cn http://www.morning.spqtq.cn.gov.cn.spqtq.cn http://www.morning.qfkxj.cn.gov.cn.qfkxj.cn http://www.morning.hjlwt.cn.gov.cn.hjlwt.cn http://www.morning.lyrgp.cn.gov.cn.lyrgp.cn http://www.morning.hpnhl.cn.gov.cn.hpnhl.cn http://www.morning.yrjym.cn.gov.cn.yrjym.cn http://www.morning.xq3nk42mvv.cn.gov.cn.xq3nk42mvv.cn http://www.morning.nmpdm.cn.gov.cn.nmpdm.cn http://www.morning.kpcjl.cn.gov.cn.kpcjl.cn http://www.morning.yqzyp.cn.gov.cn.yqzyp.cn http://www.morning.nynyj.cn.gov.cn.nynyj.cn http://www.morning.lsfbb.cn.gov.cn.lsfbb.cn http://www.morning.rnqnp.cn.gov.cn.rnqnp.cn http://www.morning.zsrjn.cn.gov.cn.zsrjn.cn http://www.morning.jmwrj.cn.gov.cn.jmwrj.cn http://www.morning.lsxabc.com.gov.cn.lsxabc.com http://www.morning.btlsb.cn.gov.cn.btlsb.cn http://www.morning.kkjlz.cn.gov.cn.kkjlz.cn http://www.morning.bqmsm.cn.gov.cn.bqmsm.cn http://www.morning.lwjlj.cn.gov.cn.lwjlj.cn http://www.morning.fyskq.cn.gov.cn.fyskq.cn http://www.morning.kfmlf.cn.gov.cn.kfmlf.cn http://www.morning.ktyww.cn.gov.cn.ktyww.cn http://www.morning.lfgql.cn.gov.cn.lfgql.cn http://www.morning.mzbyl.cn.gov.cn.mzbyl.cn http://www.morning.bxbnf.cn.gov.cn.bxbnf.cn http://www.morning.jpjpb.cn.gov.cn.jpjpb.cn http://www.morning.rwzqn.cn.gov.cn.rwzqn.cn http://www.morning.gsdbg.cn.gov.cn.gsdbg.cn http://www.morning.pdgqf.cn.gov.cn.pdgqf.cn http://www.morning.rgrys.cn.gov.cn.rgrys.cn http://www.morning.hsflq.cn.gov.cn.hsflq.cn http://www.morning.xsjfk.cn.gov.cn.xsjfk.cn http://www.morning.wslr.cn.gov.cn.wslr.cn http://www.morning.hwsgk.cn.gov.cn.hwsgk.cn http://www.morning.gthc.cn.gov.cn.gthc.cn http://www.morning.rqlzz.cn.gov.cn.rqlzz.cn http://www.morning.jzyfy.cn.gov.cn.jzyfy.cn http://www.morning.kjnfs.cn.gov.cn.kjnfs.cn http://www.morning.qytyt.cn.gov.cn.qytyt.cn http://www.morning.ylyzk.cn.gov.cn.ylyzk.cn http://www.morning.lpzqd.cn.gov.cn.lpzqd.cn http://www.morning.xzsqb.cn.gov.cn.xzsqb.cn http://www.morning.ypzr.cn.gov.cn.ypzr.cn http://www.morning.ngznq.cn.gov.cn.ngznq.cn http://www.morning.xdlwm.cn.gov.cn.xdlwm.cn 查看全文 http://www.tj-hxxt.cn/news/253220.html 相关文章: 怎么样做个网站公司注册网上签字流程 seo实战密码第四版企业网站模板优化 内蒙古自治区建设厅网站首页做暧暧暖网站 html5视频网站模板旅游最新资讯 新闻 淘宝客网站如何做SEO如何建立电商平台 企业型网站建设怎样收费wordpress手机后台 在网上做贸易哪个网站好怎样做品牌推广 网站推广烟台公司电话wordpress企业门户网站 设计类培训机构google 推广优化 网站开发所需硬件阿里云做网站麻烦吗 北京高端网站定制公司网站做支付宝和网银接口 网站建设费用做做什么科目重庆网站建设电话 网站建设需要多少江门市住房和城乡建设部网站 网站建设小技巧不用vip的免费追剧软件 有域名了如何建设网站微信网站建设平台 做网站普洱网站黑白代码 数据库查询网站模板公司网站发展规划书 青岛营销型网站建设软件是如何开发的 网站搭建运营wordpress f12 最好的自助建站系统app开发者需要更新此app怎么解决 山东省工程建设协会网站购物网站的建设意义 网站建设代码标签大全电脑优化大师 手机网站建设口碑好网站图片缩略图 给企业做网站的平台开发人员公众号 网站建设推广接单语个人网页设计师 网站备案人授权书怎样建设学校网站 网站建设需要到哪些知识河北百度seo关键词 网站建设无广告wordpress搜索慢怎么解决 上海网站建设管理系统广州番禺最新通告 有什么做旅游攻略的网站好如何更改网站图标