《设计模式补充》PPT课件.ppt_第1页
《设计模式补充》PPT课件.ppt_第2页
《设计模式补充》PPT课件.ppt_第3页
《设计模式补充》PPT课件.ppt_第4页
《设计模式补充》PPT课件.ppt_第5页
已阅读5页,还剩54页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

-1-,内容安排,设计模式举例 策略模式 适配器模式 工厂模式 单件模式 模板方法模式,-2-,从模拟鸭子游戏开始,Joe成功开发了模拟鸭子游戏SimUDuck 采用OO技术 Duck中display抽象方法,绿头鸭子,红头鸭子,-3-,需求变了,新需求 希望模拟的鸭子会飞 初步的解决方案:在Duck中增加fly()方法,所有鸭子就会飞了,-4-,橡皮鸭飞起来了!,问题来了 基类中的fly()方法导致所有子类均继承给方法,但并不是所有的子类都需要fly()方法; 为了复用(reuse)而使用继承,往往存在问题!,覆盖了橡皮鸭的叫声,-5-,覆盖橡皮鸭中的fly,勉强的解决方案 在橡皮鸭中覆盖fly()方法 Fly() /什么也不干 如果加入诱饵鸭,不会飞也不会叫,如何?,-6-,提炼接口,继承可能不是答案 需要经常添加不同的鸭子产品,都要检查并覆盖方法 新的解决方案:定义接口,-7-,评价方案,接口的问题 随着Duck的子类越来越多,每种鸭子都要实现相应的接口,重复代码越来越多,代码无法复用,-8-,软件开发的不变真理,不管你在何处工作,构建什么,用什么语言编程,伴随软件开发的不变真理 Change 不管软件当初设计的多么好,一段时间之后,总是需要成长与改变。,-9-,问题分析,问题 鸭子的行为在子类中不断变化,继承难以解决该问题,让所有子类继承这些行为是不恰当的 Flyable和Quackable接口,想法不错,但Java接口没有实现代码,造成代码无法复用,代码在子类中重复 设计原则 找出应用中可能需要变化的地方,把它们独立出来并“封装”起来,不要和哪些不需要变化的代码混合在一起 变化的部分取出并封装后,便于以后的改动或扩充,而不影响其它部分 变化的东西:鸭子的行为,-10-,提取并封装类,将Duck类中fly和quack方法提取出来 它们是子类中的易于变化的部分 定义fly相关的类,封装鸭子的fly行为 定义quack相关的类,封装鸭子的quack行为 初步设想 在独立的类中定义鸭子的行为; 在Duck中包含“指定”的行为,甚至可以在运行时动态改变行为,-11-,鸭子行为类的设计,设计原则 针对接口编程,而不是针对实现编程 定义行为接口及其实现 FlyBehavior和QuackBehavior接口,定义具体的行为类实现该接口 Duck类依赖行为接口,不关心行为的具体实现 原来做法的问题:行为或者在Duck类中实现,或者继承某个接口而在子类中实现,依赖实现细节。,-12-,鸭子行为类的设计,-13-,鸭子类的设计,public class Duck QuackBehavior quackBehavior; . public void performQuack() quackBehavior.quack(); ,public class MallardDuck extends Duck public MallardDuck() quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); . ,-14-,动态绑定鸭子行为,public class Duck public void setFlyBehavior(FlyBehavior fb)() flyBehavior=fb; public void setQuackBehavior(QuackBehavior qb) quackBehavior=qb; ,-15-,整体结构,-16-,“有一个”比“是一个”更好,有一个HasA 每个鸭子都有一个FlyBehavior和QuackBehavior,将飞行和叫的行为委派给它们处理 与继承不同,鸭子的行为通过组合(composition)其它对象得到 组合具有很大的弹性,封装易变的行为部分,甚至可以动态改变行为 设计原则 多用组合,少用继承,-17-,策略模式的定义,策略模式Strategy Pattern:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户 算法族:可以是具体的算法或行为,如不同的飞行行为和叫法,-18-,内容安排,设计模式举例 策略模式 适配器模式 工厂模式 单件模式 模板方法模式,-19-,适配器?Adapter,生活中的适配器 要在欧洲国家使用美国制造的笔记本,需要使用一个交流的适配器,通过适配器改变了插座的接口 面向对象适配器,-20-,简单的鸭子类设计,鸭子接口 public interface Duck publilc void quack(); public void fly(); 鸭子子类 public class MallardDuck implements Duck public void quack() . public void fly() ,-21-,火鸡类,火鸡接口 public interface Turkey publilc void gobble(); public void fly(); 火鸡子类 public class WildTurkey implements Turkey public void gobble() . public void fly() ,-22-,让火鸡冒充鸭子,现在缺少鸭子对象,想用火鸡对象来冒充 接口不同,不能直接代替 通过适配器来解决 public class TurkeyAdapter implements Duck Turkey turkey; public TurkeyAdapter(Turkey t) this.turkey=t; public void quack() turkey.gobble(); ,-23-,类结构,-24-,冒充吧测试代码,public class TestDriver public static void main(String args) WildTurkey turkey = new WildTurkey(); Duck turkeyAdapter = new TurkeyAdapter(turkey); testDuck(turkeyAdapter); static void testDuck(Duck duck) duck.quack(); duck.fly(); ,用户看到的只是实现了Duck接口的 TurkeyAdapter,-25-,适配器模式的定义,适配器模式Adapter Pattern:将一个类的接口,转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以合作无间 通过适配器,可以让客户从实现的接口中解耦 OO原则:使用对象组合,-26-,内容安排,设计模式举例 策略模式 适配器模式 工厂模式 单件模式 模板方法模式,-27-,关于针对接口编程,OO原则 针对接口编程,不要针对实现编程 new运算符:实例化一个具体类? 当有一群相关的具体类时,往往需要根据条件实例化某个具体类,Duck duck; if(picnic) duck = new MallardDuck(); else if(hunting) duck = new DecoyDuck(); ,-28-,问题分析,针对接口编程的好处 可以隔离以后系统可能发生的变化 如果针对接口编程,借助多态,系统可以适应任何实现接口的新类 代码使用大量的具体类时,系统非常僵硬,一旦需要加入新类,必须修改代码 直接使用具体类时违背的原则 对扩展开发,对修改关闭 解决策略:找出系统中变化的部分,从不变部分分离,-29-,匹萨店制作匹萨,订购匹萨,Pizza orderPizza() Pizza pizza = new Pizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; ,希望Pizza为抽象类或接口,-30-,需要更多的匹萨类型,Pizza orderPizza(String type) Pizza pizza; if(type.equal(“cheese”) pizza = new CheesePizza(); else if(type.equal(“greek”) pizza = new GreekPizza(); else if(.) pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; ,-31-,无法对修改关闭!,Pizza orderPizza(String type) Pizza pizza; if(type.equal(“cheese”) pizza = new CheesePizza(); else if(type.equal(“greek”) pizza = new GreekPizza(); else if(type.equal(“clam”) pizza = new CalmPizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; ,这是不变部分,这是变化部分 无法对修改关闭!,-32-,抽取创建匹萨的代码,Pizza orderPizza(String type) Pizza pizza; pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; ,if(type.equal(“cheese”) pizza = new CheesePizza(); else if(type.equal(“greek”) pizza = new GreekPizza(); else if(type.equal(“clam”) pizza = new CalmPizza();,-33-,封装创建匹萨的代码,public class SimplePizzaFactory public Pizza createPizza(String type) Pizza pizza = NULL; if(type.equal(“cheese”) pizza = new CheesePizza(); else if(type.equal(“greek”) pizza = new GreekPizza(); else if(type.equal(“clam”) pizza = new CalmPizza(); return pizza; ,封装创建匹萨的过程,变化时只需要修改该简单工厂,-34-,重整匹萨店PizzaStore,public class PizzaStore SimplePizzaFactory factory; public PizzaStroe(SimplePizzaFactory f) this.factory=f; public Pizza orderPizza(String type) Pizza pizza; pizza = factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; ,-35-,重整匹萨店PizzaStore,-36-,加盟匹萨店,希望在不同地方开设分店 加盟店根据区域特点,需要提供不同风味的匹萨,但需要控制匹萨的制作过程 创建不同区域的各自的匹萨工厂 NYPizzaFactory nyFactory=new NYPizzaFactory(); PizzaStore nyStore=new PizzaStroe(nyFactory); nyStore.orderPizza(“Veggie”);,不同的工厂,除了改变风味外,可能也会改变制作流程!,-37-,给匹萨店设置框架,public abstract class PizzaStore public Pizza orderPizza(String type) Pizza pizza; pizza = createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; abstract Pizza createPizza(String type); ,这些不许变化,每个匹萨店子类必须实现自己的匹萨创建, 但匹萨的制作、包装过程严格受控,-38-,允许子类做决定,PizzStore有成熟的订购系统,由orderPizza处理 保证所有加盟店的订单处理一致 每个PizzaStore的子类必须重新实现createPizza,实现不同风味的匹萨,-39-,开一家匹萨店,public class NYPizzaStore extends PizzaStore Pizza createPizza(String type) if(type.equal(“cheese”) return new NYStyleCheesePizza(); else if(type.equal(“clam”) return new NYStyleClamPizza(); else return null; ,-40-,类结构,创建者,产品,-41-,定义工厂方法模式,工厂方法模式Factory Mothed Pattern:定义一个创建对象的接口,但由子类决定要实例化的类(产品类)是那一个。工厂方法让类把实例化推迟到子类 “工厂方法让子类决定要实例化的类”,不是指子类本身存在决定的逻辑,而是根据用户选择的工厂类型,从而决定了创建的产品类型,-42-,不用工厂方法,若不使用工厂方法,则对匹萨店PizzaStore的依赖很强,public Pizza createPizza(String style, String type) Pizza pizza = null; if(style.equals(“NY”) if(type.equals(“cheese”) pizza = new NYStyleCheesePizza(); else if(type.equals(“clam”) pizza = new NYStyleClamPizza(); if(style.equals(“Chicago”) pizza.prepare(); pizza.bake(); . return pizza; ,匹萨店的createPizza方法 依赖所有具体的匹萨类的实现 任何具体匹萨的改变都会影响 到匹萨店,-43-,依赖倒置原则,要依赖抽象,不要依赖具体类 不能让高层组件依赖低层组件,两者都应该依赖抽象 PizzaStore是高层组件 匹萨的实现是低层组件,PizzaStore依赖了具体匹萨 修改代码:依赖抽象,-44-,依赖倒置,-45-,内容安排,设计模式举例 策略模式 适配器模式 工厂模式 单件模式 模板方法模式,-46-,循序渐进推导单件模式,如何创建一个对象 new MyClass(); 如何创建一个类的唯一实例 只要是公开的类,就可以多次实例化它 如果不是公开的类,同一个包内的类可以实例化它多次 私有构造器 public MyClass private MyClass() 含有私有构造器的类不能被实例化,-47-,循序渐进推导单件模式,什么地方可以访问私有构造器 在MyClass内部的代码能调用私有构造器代码,但由于MyClass无法实例化,导致矛盾的逻辑 解决之道:静态方法 静态方法是一个类方法 public MyClass private MyClass() public static MyClass getInstance() return new MyClass(); ,-48-,单件模式,public class Singleton private static Singleton uniqueInstance; private Singleton() public static Singleton getInstance() if(uniqueInstance=null) uniqueInstance=new Singleton(); return uniqueInstance; ,此部分代码在多线程情况需要完善,-49-,单件模式的定义,单件模式Singleton Pattern:确保一个类只有一个实例,并提供一个全局访问点 把某个类设计成自己管理的一个单独实例,避免其它类再自行产生实例。要想获得单件实例,单件模式是唯一途径 单件模式提供全局的访问点,当需要实例时,向类查询并返回单个实例,-50-,内容安排,设计模式举例 策略模式 适配器模式 工厂模式 单件模式 模板方法模式,-51-,咖啡和茶的冲泡方法,把水煮沸 用沸水冲泡咖啡 把咖啡倒入杯子 加糖和牛奶,把水煮沸 用沸水冲泡茶叶 把茶倒入杯子 加柠檬,冲泡咖啡,冲泡茶叶,-52-,咖啡类,public class Coffe void prepareRecipe() boilWater(); brewCoffeGrinds(); pourInCup(); addSugarAndMilk(); public void boilWater() . public void brewCoffeGrinds(). public void pourInCup(). public void addSugarAndMilk(). ,-53-,茶类,public class Tea void prepareRecipe() boilWater(); steepTeaBag(); pourInCup(); addLemon(); public void boilWater() .

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论