




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、设计模式1 2 4 用GoF设计模式设计用例实现适配器模式GoF工厂模式GoF单子模式GoF策略模式GoF组合模式GoF外观模式GoF观察者/发布订阅/委托事件模式GoF1.适配器模式在POS系统中,需要和多个外部系统交互库存系统、税金计算器、账务系统等。以使用第三方税金计算器为例使用A计算器TaxA atax= new TaxA();TaxA.tax(,);使用B计算器TaxB atax= new TaxB();TaxB.getTax(,);代码中有两个容易变化的地方:计算器的类名、计算器提供的方法名2。使用适配器来屏蔽接口的差异 class TaxAdaptor TaxA tax=new
2、TaxA(); float getTaxes() return tax.tax(); 3。代码变为TaxAdaptor adaptor ;adaptor =new TaxAAdaptor();adaptor.getTaxes(.); TaxBdaptor adaptor ;adaptor =new TaxBAdaptor();adaptor.getTaxes(.);接口统一了,但是代码还是和具体的类耦合!继续想方法!4。创立适配器的抽象来屏蔽不同的适配器ITaxCalculatorAdaptor adaptor ;adaptor =new TaxAAdaptor();adaptor.getTa
3、xes(.); ITaxCalculatorAdaptor adaptor ;adaptor =new TaxBAdaptor();adaptor.getTaxes(.); 现在,就剩红色字体处要出来啦继续想方法! 6 4 用GoF设计模式设计用例实现1.适配器模式问题:如何解决接口不兼容的问题或为不同接口但相似的组件提供一个稳定的接口?解决方案:通过一个中间的适配器对象将组件的原来接口转换为另一个接口。4 用GoF设计模式设计用例实现-适配器模式适配器模式类图 7 8 4 用GoF设计模式设计用例实现-适配器模式SAPAccountingAdaptor负责将postSale接口适配成外部效劳
4、的接口clientAdapterAdaptee有一个类(adaptee)实现了数学中的幂次运算,方法中需要传入两个参数,一个是基数base,另外一个是幂次exp。现在客户端需要一个求得一个数的平方的函数接口(target),传入一个数,得到它的平方值。请应用适配器模式进行设计,绘制类图。 9 10 4 用GoF设计模式设计用例实现2工厂模式2.工厂模式考虑:在前面外部效劳适配器解决方案中,谁去负责创立这些适配器?谁去确定要创立的是哪个适配器,是TaxMasterAdapter 还是GoodAsGoldTaxProAdapter?让领域类如Sale来创立适配器对象是否适宜?-如此那么领域类不只是
5、包含应用逻辑了!一个设计原那么:设计要保证别离不相关的事物。别离不同的事物到不同的领域,从而使得别离的各局部能到达高内聚的设计目标。5。应用工厂模式来屏蔽具体适配器ITaxCalculatorAdaptor adaptor;ServiceFactory factory=new ServiceFactory();adaptor =factory.getTaxCalculatorAdaptor();adaptor.getTaxes(.); 现在,代码彻底和具体的适配器类无关啦6。工厂中如何与具体适配器类解耦1具体用哪个适配器?用属性来记录System.setProperty(name,zhouch
6、unyan)System.setProperty(ITaxCalculatorA, TaxAAdaptor);2工厂中的getTaxCalculatorAdaptor与具体适配器解耦ITaxCalculatorAdaptor getTaxCalculatorAdaptor() if(taxCalculatorAdaptor=null) String className=System.getProperty(ITaxCalculatorA); taxCalculatorAdaptor=Class.forname(classNam
7、e).newinstance() return taxCalculatorAdaptor; 13 4 用GoF设计模式设计用例实现2工厂模式问题:当考虑某些特殊情况时,如复杂的创立逻辑、希望别离创立职责以产生更好的内聚度等,谁应该负责创立对象?解决方案:创立一个名为工厂的纯虚构对象来处理创立。工厂类ServiceFactory负责创立第三方财务适配器、库存适配器、税金计算器。if ( taxCalculatorAdapter = null ) /创立某一税率计算器对象赋值给 /taxCalculatorAdapter ; return taxCalculatorAdapter;返回值类型?类型
8、?getTaxCalculatorAdapter() : 返回类型是TaxMasterAdaptor还是 GoodAsGoldTaxProAdaptor?还是 14 4 用GoF设计模式设计用例实现2工厂模式注意:工厂方法返回对象的类型是接口,而不是类,这样工厂方法就可以返回接口的任何实现。注意:在serviceFactory中,决定哪个类的实例被初始化是从外部数据源读入类名如在java中可使用系统属性,然后动态装载此类来实现的。 if(taxCalculatorAdaptor=null) String className=System.getProperty(taxCalculator.cl
9、); taxCalculatorAdaptor= (ITaxCalculatorAdaptor)Class.forName(className).newInstance(); return taxCalculatorAdaptor; 15 4 用GoF设计模式设计用例实现2工厂模式补充依赖倒置原那么(DIP)告诉我们应该优先依赖于抽象类,而防止依赖于具体类。当这些具体类不稳定时,更应该如此。因此,下面的代码违反了这个原那么Circle c = new Circle(); 16 4 用GoF设计模式设计用例实现2工厂模式改进:工厂模式允许我们只依赖于抽象接口就能创立出具体类的实例
10、。public interface ShapeFactory public Shape make(String shapeName) throws Exception; 17 4 用GoF设计模式设计用例实现2工厂模式public class ShapeFactoryImplementation implements ShapeFactory public Shape make(String shapeName) throws Exception if (shapeName.equals(Circle) return new Circle(); else if (shapeName.equal
11、s(Square) return new Square(); else throw new Exception(ShapeFactory cannot create + shapeName); 18 4 用GoF设计模式设计用例实现3单子模式3.单子模式谁创立工厂类?如何访问此类?事实:整个程序只需要一个工厂类的实例;由于代码在不同的地方需要访问适配器以调用外部系统的效劳,所以工厂类的方法也需要在代码的多个地方被调用。问题:一个类X只能有一个实例这就是“单子的含义)。对象需要全局的可见性和单一的访问点。解决方案:为类X定义静态方法getInstance,该方法返回X的唯一实例。因为是静态方法,
12、所以可以全局访问,且该类的构造方法可见性设为私有private。 19 4 用GoF设计模式设计用例实现3单子模式/单子方法getlnstance返回工厂类的唯一实例public static synchronized ServicesFactory getlnstance() if ( instance = null ) instance = new ServicesFactory(); return instance; 20 4 用GoF设计模式设计用例实现3单子模式Synchronized解释:单子类的getInstance方法经常被调用,在多线程MultiThread的应用程序里,在某
13、一客户端线程调用getInstance方法前,必须先把该方法锁住,以防止其他客户端调用该方法;当方法调用完毕后,再把锁翻开,让其他客户端线程可以调用该方法。从而实现线程的并发控制。 21 4 用GoF设计模式设计用例实现3单子模式public class Register IAccountingAdapter accountingAdapter; public void initialize() do some work . accountingAdapter = ServicesFactory.getlnstance().getAccountingAdapter(); do some wor
14、k . / other methods. ServicesFactory具有全局可见性Register对工厂类的调用: 22 4 用GoF设计模式设计用例实现3单子模式ServicesFactory.getlnstance().getAccountingAdapter();通过单子模式得到该实例的可见性 23 4 用GoF设计模式设计用例实现外部接口变化的解决方案register向外部SAP财务系统发送PostSaleregister从工厂类中获取针对SAP财务系统的适配器SAPAccountingAdaptor;Register向SAPAccountingAdaptor发送PostSale消
15、息,由适配器将消息适配后转发给外部SAP财务系统。请画出以上交互的顺序图 24 4 用GoF设计模式设计用例实现外部接口变化的解决方案适配器模式、多态模式、工厂模式、单子模式的综合运用 25 目的:实现复杂的定价规那么。商店的定价策略可能变化。对变化的定价算法我们应如何设计?策略模式语境/问题:如何对变化或与变化相关的算法或策略进行设计?如何设计系统使得其具有改变算法或策略的能力?解决方案:在单独的类中分别定义每种算法、策略和政策,并且使其具有公共接口。4 用GoF设计模式设计用例实现4策略模式 26 4 用GoF设计模式设计用例实现4策略模式用多态屏蔽变化一种策略对应于一个类 27 4 用G
16、oF设计模式设计用例实现4策略模式策略对象依附于语境对象,策略对象对其应用算法。本例中Sale是语境对象。当getTotal消息发给Sale时,它会把局部工作委派给它的策略对象。通常,发给语境对象的消息和发给策略对象的消息会同名。语境对象会把自身的引用传递给策略对象,使得策略对象对语境对象拥有参数 可见性,便于将来的协作。调用策略对象获取折扣后总价格 28 4 用GoF设计模式设计用例实现4策略模式语境对象需要其策略对象的属性可见性Sale需要其策略的属性可见性注意:Sale和ISalePricingStrategy接口关联,而不是和具体策略类关联。这就可以使接口的任何实现都可以与Sale的p
17、ricingStrategy属性绑定。对象如何获取策略对象的可见性 29 4 用GoF设计模式设计用例实现4策略模式谁来负责创立策略对象:工厂类出于内聚的考虑,创立专门用于生成策略对象的工厂类:PricingStrategyFactory注意:策略工厂不需要缓存策略类的实例,因为策略是经常变化的。应该在每次要用的时候进行实例化。对象如何获取策略对象的可见性 30 4 用GoF设计模式设计用例实现4策略模式在sale的初始化时获取策略对象的引用对象如何获取策略对象的可见性 31 示意代码:Public class sale ISalePricingStrategy ps; public sale
18、()/构造方法 psPricingStrategyFactory.getInstance(). getSalePricingStrategy Public Money getTotal /计算折扣前的各saleLineItem销售价格总和; return ps.getTotal(this;/代码只和接口打交道 4 用GoF设计模式设计用例实现4策略模式练习:假设现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。对所有的教材类图书实行每本一元的折扣;对连环画类图书提供每本7%的促销折扣;而对非教材类的计算机图书有3%的折扣;对其余书没有折扣。请应用策略模式进行设计,绘制类图 32 33 34
19、 4 用GoF设计模式设计用例实现5组合模式现实情况:一次销售可能有多个定价策略;定价策略与顾客类型有关如高级会员;定价策略可能和所购置商品的类型有关如Darjeerling茶面临问题是否存在一种方式,可以改变设计,使得Sale对象不知道是一个还是多个定价策略与其关联,并同时提供一种设计来解决定价策略冲突? 35 4 用GoF设计模式设计用例实现5组合模式组合模式语境/问题:如何象对待原子对象一样对一组对象或对象的组合结构做同样多态的处理?解决方案:定义组合对象和原子对象的类,使得他们实现同样的接口。 36 组合模式的一般形式原子对象组合对象 37 4 用GoF设计模式设计用例实现5组合模式组
20、合对象的显著特征:组合对象包含一系列原子对象,这两类对象实现相同的接口。对Sale附加的策略既可以是组合策略,又可以是原子策略,而Sale不用去关心到底是哪类策略。组合类strategies 38 4 用GoF设计模式设计用例实现5组合模式要解决的关键问题:Sale如何获取组合策略对象的引用?组合策略对象由谁创立?Sale发消息给组合策略对象时,组合策略对象如何进一步调用简单策略对象来计算销售折扣后总价格? 39 4 用GoF设计模式设计用例实现5组合模式存放简单策略将简单策略参加组合策略中1. 抽象类CompositePricingStrategy的定义 40 4 用GoF设计模式设计用例实
21、现5组合模式2.子类CompositeBestForCustomerPricingStrategy的定义 41 4 用GoF设计模式设计用例实现5组合模式获取CompositeBestForCustomerPricingStrategy的引用在sale初始化时由策略工厂创立一个组合策略,并创立简单策略加到组合策略里;而sale并不清楚使用的是简单策略还是组合策略。在sale的getTotal方法中调用组合策略计算折扣后总价。 42 4 用GoF设计模式设计用例实现5组合模式4.调用组合策略获取销售折扣后总价格 42 43 4 用GoF设计模式设计用例实现5组合模式import java.uti
22、l.Vector;public class CompositeShape implements Shape private Vector itsShapes = new Vector(); public void add(Shape s) itsShapes.add(s); public void draw() for (int i = 0; i itsShapes.size(); i+) Shape shape = (Shape) itsShapes.elementAt(i); shape.draw(); 组合模式应用举例图形可能是Square、Circle或者由Square和Circle组
23、成的复合图形 44 4 用GoF设计模式设计用例实现6外观模式外观模式引言:学校的财务处有不同的科室,每一个科室办理专门的业务。当我们办理不同的业务时,必须先调查清楚到哪个科室去办,而且科室内的业务有办理流程,往往先得办这项任务,才能办下一项任务。如果某一个科室的某项业务被转移到其他科室去办理,如果我们事先不清楚这一变化,那可能找不到去哪办理这项业务。所以,去财务处办事不方便!而如果财务处设立一个接待员,我们只需要和接待员交互,接待员再和内部财务处人员交互,那么问题会变得非常简单。 45 同样的,系统中的子系统由类和子系统组成,这些类或子系统对外提供功能。外部的类需要和子系统中不同的类交互,来
24、实现预期的功能。如果子系统中的类名改了,类的接口改了,那么会直接影响到外部类。语境/问题:一组分散的实现类或接口例如子系统内部的接口和实现类要求一个公共的、一致的接口。如何处理与子系统元素直接耦合或子系统的实现可能变化的情况?解决方案:为子系统定义一个单一的连接点使用外观对象封装子系统,外观对象呈现一个单一的一致接口,负责客户端程序与子系统组件的交互。4 用GoF设计模式设计用例实现6外观模式 46 4 用GoF设计模式设计用例实现6外观模式外观对象对子系统实现提供了受保护变化。外部对象只被耦合到外观对象,子系统内的实现和其他组件是私有的,不能被子系统外部组件访问。 47 4 用GoF设计模式
25、设计用例实现6外观模式public class Sale public void makeLineItem( ProductDescription desc, int quantity ) SalesLineItem sli = new SalesLineItem( desc, quantity ); / call to the Faade if ( POSRuleEngineFacade.getInstance().isInvalid( sli, this ) ) return; lineItems.add( sli ); / . / end of class 练习:一个保安系统由两个录像机
26、、三个电灯、一个遥感器和一个警报器组成。保安系统的操作人员需要经常将这些仪器启动和关闭。请使用外观模式进行设计,实现仪器的启动和关闭 48 49 模式7观察者模式 50 观察者模式案例之一气象站数据发布 51 问题:气象站的湿度、温度、气压数据要发布显示到不同类型的显示装置上第一版本设计 52 53 该设计中存在的问题回忆设计原那么:将稳定的和易变的局部分开,并且将易变的局部进行封装。应用观察者模式来处理易变的显示装置。概念:主题对象、观察者 54 概念:观察者注册 55 Step1.鸭子申请注册为观察者Step2.恭喜!鸭子成为观察者啦Step3.主题对象有数据更新,通知所有观察者鸭子对象许
27、多观察者88888概念:观察者取消注册 56 Step1.不想当观察者啦,老鼠申请被除名Step2.愿望实现,老鼠被 除名老鼠对象老鼠对象许多观察者Step3.清静啦!主题对象有新数据更新时,老鼠也不会接到通知啦14141414观察者模式观察者模式定义了主题对象和观察者对象之间的一对多依赖,当主题对象的状态改变时,依赖于它的所有观察者都会收到通知并自动更新。 57 58 4 用GoF设计模式设计用例实现7观察者模式观察者模式语境/问题:不同类型的订阅者对象如窗口对发布者对象如sale的状态改变或事件感兴趣。当发布者产生一个事件时,订阅者可以按自己的方式做出响应。更进一步,发布者希望维护和订阅者
28、之间的松散耦合关系。如何实现?解决方案:定义“订阅者或“监听者接口,各种类型的订阅者实现此接口。发布者可以动态注册对其事件感兴趣的订阅者,当事件发生时通知已注册的订阅者。观察者模式:类图 59 通过引入Suject和Observer接口,将具体的发布者和观察者解耦,使得增加新的观察者不会影响到发布者,也使得观察者可以连接到新的发布者。思考:增加Subject接口有什么用意?设计原那么:交互的对象之间尽量解耦。观察者模式案例之二气象站数据发布气象站案例实现 60 上述设计是主题对象将数据Push给观察者,push哪些数据是主题对象指定的,这样就不具备灵活性,譬如各个观察者需要的数据可能是不一样的
29、,又譬如主题对象如果新增数据就要修改主题对象的notifyObservers()方法。能否改为pull方式,即主题对象提供一系列get方法来对外提供数据,观察者拥有主题对象的引用,能调用这些get方法来获取数据,获取哪些数据由观察者自己决定。Java的Built-in Observer模式能同时提供Push和Pull两种方式。 61 62 如何把对象变成观察者:实现观察者接口,然后调用任何Observable对象的addObserver()方法可观察者要如何送出通知:1先调用setChanged()方法,标记状态已经改变的事实;2然后调用两种notifyObservers()方法中的一个not
30、ifyObservers() 或 notifyObservers(Object arg)观察者如何接收通知:update(Observable o, Object arg),其中arg就是传给观察者的数据对象,采用pull模式时可观察者传null给arg。这就是我们以前所称的“主题 Subject,现在改称为“可观察者Observable。我们不需要在此提供 register()、remove()和notifyObservers()方法,因为我们已经从超类继承了这些行为。为了精简起见,此处没有绘制DisplayElement接口,但是所有的布告板仍然必须实现此接口 63 4 观察者模式应用案例之二需求当销售总额变化时,刷新GUI窗口显示的销售总额。能否在Sale改变了销售总额时,由Sale对象向窗口发送一条消息通知窗口刷新显示?模型视图别离原那么:模型对象非GUI对象,如sale应不知道视图和表示对象如窗口。它保证了表示层对象UI与其他层对象交互的低耦合度,从而允许用一个新的视图或表示层来替代已有的视图或表示层。 64 4 用GoF设计模式设计用例实现7观察者模式
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高中化学试题及答案有机化学结构与性质
- 我的校园梦想想象作文4篇范文
- 高新技术企业研发管理流程
- 畜牧业饲养与销售联合协议
- 家政服务行业知识测试卷大纲与内容框架
- 高中物理分子运动理论与实验课程教案
- 学会分享的话题作文15篇
- 在线销售授权合同协议
- 智慧农业与可持续发展目标的协调路径
- 研究成果对行业影响评估表
- 资源编排视角下立讯精密连续并购的价值创造研究
- 北师大版历史七年级下册第2课《唐太宗与贞观之治》听课评课记录
- 2025年中考化学二轮复习热点题型训练:化学思维方法(原卷版)
- 电大《11872国际经济法》期末终考题库及答案
- 贵州贵安发展集团有限公司笔试
- DG∕TJ 08-53-2016 行道树栽植技术规程
- 供应链管理在电网企业物资管理中的应用
- 《螺栓连接多层全装配式混凝土墙板结构技术规程》
- 【MOOC】《电工技术》(北京科技大学)中国大学MOOC慕课答案
- 输血科内部审核检查表
- 《绿色低碳铝评价导则及追溯指南》T CNIA 0245-2024
评论
0/150
提交评论