您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 面向对象软件设计模式
1.Observer——观察者模式——行为模式Intent:定义对象之间的一对多依赖关系,以便当一个对象更改状态时,将自动通知和更新其所有依赖项。别名:dependents,发布订阅,Model-ViewMotivation:需要在不使类紧密耦合的情况下保持相关对象之间的一致性Applicability:1.当一个抽象有两个aspect,且其中一个依赖于另一个。将这些不同的aspect封装在分离的对象中,这样就可以独立地改变和重用这些aspect.2.当对一个对象进行更改时,需要更改其他对象,但不知道需要更改多少个对象。3.当一个对象能通知其他对象,但可以不用知道这些对象是谁时,可以使用这个模式。换言之,当期望当前对象不与其它对象紧耦合时,可以使用。类图图1.1图1.2参与者:Subject:跟踪观察者的情况,提供用于附加和分离(attachinganddetach-ing)Observer对象的接口。Observer:定义了一个用于更新通知的接口。ConcreteSubject:是被观察的对象,存储ConcreteObserver对象的状态,在状态发生变化时向其观察者发送通知。ConcreteObserver:观察ConcreteSubject的状态的对象,存储应该与Subject对象保持一致的状态,实现Observer更新接口使其状态与Subject的状态保持一致。Collaboration:Advantage1.最小化了Subject和Observer之间的耦合性。可以单独复用Subject和Observer;可以在不修改Subject的情况下增加Observer;Subject知道的只有Observer的列表;Subject不需要知道观察者的具体类,只需要每个Observer实现更新接口即可;Subject和Observer可以属于不同的抽象层。2.支持事件广播。Subject发布通知给每一个订阅它的Observer;Observer可以在任何时间被添加或删除。Disadvantage1.可能会产生意外的更新。Observer不知道彼此之间的相互存在,他们可能对改变Subject的成本视而不见;Subject表面无害的操作可能导致Observer及其依赖对象的级联更新;此外,没有明确定义或维护的依赖性标准通常会导致虚假更新,这很难追查。2.简单的更新协议不提供Subject更新的细节。Observer必须自己去发现哪些细节被改变了,因此Observer需要自己推断变化。实现细节1.Subject如何跟踪自己的Observer?答:使用数组或链表保存Observer信息。2.如果一个Observer想要观察多个Subject呢?答:让Subject通过更新接口告诉Observer它是谁。3.谁触发更新?答:①Subject的状态发生改变的任何时候;②观察者在引起一个或多个状态变化之后;③一些第三方对象进行触发。4.确保Subject在发送了通知之前就完成更新。5.Subject应该给Observer发送多少变化的信息?答:①Push模式——常用;②Pull模式——少用。6.Observer可以订阅感兴趣的特定事件吗?答:如果这样的话,它就是发布订阅模式。7.Observer也可以是别的对象的Subject吗?答:当然可以。8.如果Observer想要在几个主题改变状态后才被通知怎么办?答:使用充当中介的中间对象。Subject给中间对象发送通知,中间对象可以在将消息发送给Observer之前进行必要的操作。已知用途1.Smalltalk的MVCUI框架。2.JavaAWT/Swing事件模型。Push和Pull的对比Pull模型:强调Subject对Observer是忽略的。可能效率很低,因为Observer只能自己找改变的信息,Subject不提供帮助。Push模型:假设Subject知道自己的Observer的需求,可以主动给自己的Observer发送更新通知。此时Observer不再具有可复用性,这是因为Subject对Observer进行了假设,而这些假设可能不是正确的。Java中的观察者模式Java中常将Subject命名为Observable。使用Java内置观察者模式Observer:实现Observer接口,Observable调用addObserver()方法添加。Observable:发送通知时,调用setChange()方法标记改变的状态,然后调用notifyObservers()或notifyObservers(Objectarg)方法,arg是数据对象。Observer接收通知:调用update()方法。如果要将数据“Push”给Observer,可以将数据作为数据对象传递给notifyObserver(Objectarg)方法。如果不这样,那么Observer必须从传递给它的Observable对象中“Pull”它想要的数据。Java内置观察者的缺点Observable是一个类,因此使用时必须继承。Observable保护关键方法。setChanged()方法是protected权限,因此要用该方法时必须使用类的继承来继承Observable类,违反了“优先使用组合而非继承”。2.Strategy——策略模式——行为模式设计原则:①把可能变化的代码独立出来,不要和不变化的代码混在一起。将变化部分的代码提取出来,采取各种变化并“封装”它,以便它不会影响代码的其余部分。②针对接口编程,而不是针对实现编程。这样也满足依赖倒置原则。③多用聚合,少用继承。HAS-A比IS-A更好。使用聚合创建系统可以提供更大的灵活性。它不仅将一系列算法封装到自己的类集中,而且还允许在运行时更改指定的行为。Intent:针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。客户可以自己决定使用哪个算法。别名:Policy。Motivation:1.如果client支持多种算法,这就会使得client变得更大且更难以维护。2.不同算法适合于不同的时间和场景,如果我们不想支持多种算法的话,可以不使用。3.新增一种算法和修改原来已有的算法,是很困难的。Applicability1.许多相关类仅在行为上有所不同。策略模式提供了一种使用多种行为之一配置类的方法。2.针对同一个操作,需要使用不同的算法时。当这些算法按照类的层次结构实现时,可以使用策略模式。3.算法使用client不应该知道的数据时,使用策略模式可避免暴露复杂的特定于算法的数据结构。4.类定义了许多行为,这些行为在其操作中显示为多个if语句。为了减少这些if语句,可以将相关的条件分支移动到自己的Strategy类中。类图参与者:Strategy:声明所有支持算法的通用接口。Context使用此接口调用Concrete-Strategy定义的算法。ConcreteStrategy:实现Strategy接口中的算法。Context:配置了ConcreteStrategy对象,维护对Strategy对象的引用,可以定义一个让Strategy访问其数据的接口。Collaborations:Strategy和Context交互来实现被选中的算法。在调用算法时,Context可以将算法所需的所有数据传递给Strategy。Context也可以将自身作为Strategy操作的参数传递,这使Strategy可以根据需要回调Context。Context将客户端的请求转发给其对应的Strategy。通常,有一系列Con-creteStrategy供client选择。Client通常会创建并传递ConcreteStrategy对象给Context。Client仅与Context进行交互,而不与ConcreteStrategy交互。Advantage1.支持实现相关算法族。Strategy的层次结构定义了一系列用于重用Context的算法或行为。2.可以替代继承。将算法封装在单独的Strategy中可,就可以实现独立于其Context改变算法,从而更容易切换、理解和扩展(switch,understand,andextend)。3.可以极大减少if语句的使用。策略模式提供了用于选择所需行为的if语句的替代方案。4.提供了可选择的不同实现。Strategy可以提供相同行为的不同实现,client可以根据不同的时间和空间选择合适的Strategy。Disadvantage1.client必须要注意不同的Strategy。client必须先了解每个Strategy的不同之处,然后才能选择合适的Strategy,这无疑增加了client使用Strategy的难度。2.增加了Strategy与Context之间的通信开销。无论ConcreteStrategy是复杂还是简单,它们都共享一个Strategy,而一些ConcreteStrategies(比如简单的那些)可能不会使用Context传递的所有信息。3.增加了对象的数量。只有不通过调用来维护状态的共享Strategy才能减少对象的数量。扩展扩展一:Context与Strategy之间的数据传递Strategy和Context必须使Concrete-Strategy能够从Context中有效访问所需的任何数据,反之亦然。一种方法是让Context将数据以参数的形式传递给Strategy操作。这样的好处是简单,可以让Context和Strategy解耦;但坏处是Context可能传递给Strategy不需要的数据。另一种方法是Context将自身作为参数传递,Strategy明确地从Context请求数据。Strategy可以存储对其Context的引用,从而无需传递任何内容。但Context必须为其数据定义更精细的接口,这将更使得Strategy和Context更加紧耦合。扩展二:使得Strategy对象可选如果Context不具有Strategy也是有意义的,那么我们可以简化Context。Context在访问Strategy之前需要查看它是否具有Strategy对象。如果具有Strategy对象,则可以正常地直接访问;如果没有Strategy对象,那么Context执行默认行为。一个Strategy是否可以被视为默认Strategy,取决于Context。3.FactoryMethod——工厂方法——创建型模式关键字“new”的问题:使用new时肯定会实例化一个具体的类,所以这肯定是一个实现,而不是接口。Intent:定义用于创建对象的接口,但让子类决定实例化哪个类。别名:VirtualConstructorMotivation:使用new时肯定会实例化一个具体类,所以这肯定是一个实现而不是接口。Applicability:①要求Concreteproduct不要暴露给client;②Creator无法决定它必须创造的具体产品;③Creator希望其子类指定它创建的产品;④Creator将创建实例的责任委托给多个子类之一。类图:参与者:Product:一个接口,用于定义工厂需要创建的对象。ConcreteProduct:Product接口的实现。Creator:一个抽象类或接口,声明了工厂方法,该方法返回Product类型的对象。Creator还可以定义工厂方法的默认实现,该实现返回默认的ConcreteProduct对象。ConcreteCreator:重写工厂方法,返回由Product引用的ConcreteProduct实例。CollaborationCreator依赖其子类来实现工厂方法,以便它返回相应ConcreteProduct的实例。Advantage通过将新编写的代码放到一个对象或方法中,来避免代码冗余,并提高了可维护性。client仅依赖于接口而不是实例化对象所需的具体类。这样就实现了面向接口编程,而不是面向实现编程。Disa
本文标题:面向对象软件设计模式
链接地址:https://www.777doc.com/doc-3354273 .html