版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第1章初识设计模式-2-本章目标了解设计模式的概念了解设计模式的历史理解设计模式的要素掌握设计模式的分类设计模式的概念定义:设计模式(DesignPattern)是一套被反复使用、多数人知晓的、经过分类编目的优秀代码设计经验的总结目的:使用设计模式是为了重用代码、使代码更易理解并保证代码的可靠性原理:
面向接口编程,而不是面向实现原则:
降低耦合,增强灵活性-3--4-设计模式的历史起源于建筑设计ErichGamma、RichardHelm、RalphJohnson和JohnVlissides《DesignPatterns:ElementsofReusableObject-OrientedSoftware(设计模式:可复用面向对象软件的基础)》-5-设计模式的要素和分类模式名称问题环境或初始环境解决方案效果举例末态环境推理其他有关模式已知应用创建型结构型行为型设计模式的要素设计模式的分类-6-创建型设计模式创建型模式是用来创建对象的模式,抽象了实例化的过程,帮助一个系统独立于其关联对象的创建、组合和表示方式
创建型模式具有两个功能将系统所使用的具体类的信息封装起来隐藏类的实例是如何被创建和组织的。外界对于这些对象只知道它们共同的接口,而不清楚其具体的实现细节Roomroom=newModernRoom();//现代风格房屋Roomroom=newClassicalRoom();
//古典风格房屋RoomFactoryfactory=newModernRoomFactory();RoommodernRoom=factory.create();RoomFactoryfactory=newClassicalRoomFactory();RoomclassicalRoom=factory.create();单例模式(SingletonPattern)工厂方法模式(FactoryPattern)抽象工厂模式(AbstractFactory)建造者模式(BuilderPattern)原型模式(PrototypePattern)-7-结构型设计模式代理模式(Proxy)
为其他对象提供一种代理以控制对该对象的访问
装饰模式(Decorator)
动态地给一个对象添加一些额外的职责适配器模式(Adapter)
将一个类的接口变换成客户端所期待的另一接口
组合模式(Composite)
将对象组合成树形结构以表示“部分-整体”的层次结构桥梁模式(Bridge)
将抽象和实现解耦,使得两者可以独立的变化外观模式(Facade)
要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行
享元模式(Flyweight)
池技术的重要实现方式,使用共享对象可有效地支持大量的细粒度的对象-8-行为型设计模式-1模板方法模式(TemplateMethod)
定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤命令模式(Command)
将一个请求封装成一个对象,从而使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能责任链模式(ChainofResponsibility)
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止策略模式(Strategy)
定义一组算法,将每个算法都封装起来,并且使它们之间可以互换迭代器模式(Iterator)
访问一个容器对象中的各个元素,而又不需要暴露该对象的内部细节-9-行为型设计模式-2中介者模式(Mediator)
用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示的相互作用,从而使其耦合松散,而且可以独立的改变他们之间的交互观察者模式(Observer)
定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新责任链备忘录模式(Memento)
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态访问者模式(Visitor)
封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作状态模式(State)
当一个对象内在状态改变时允许其改变行为解释器模式(Interpreter)
给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该文法表示来解释语言中的句子-10-小结设计一个模式的过程就是将问题抽象化,忽略不重要的细节后发现问题的本质,并找到普遍适用的解决方案的过程GoF的《设计模式》提供了一套可复用的面向对象技术设计模式起源于建筑设计学设计模式的基本要素是:名字、问题、初始环境、举例、末态环境、推理、其他有关模式、已知应用设计模式主要有23种,可以将这些模式划分为三大类型:创建型、结构型和行为型创建型包括:单例模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式结构型包括:代理模式、装饰模式、适配器模式、组合模式、桥梁模式、外观模式和享元模式行为型包括:模板方法模式、命令模式、责任链模式、策略模式、迭代器模式、中介者模式、观察者模式、备忘录模式、访问者模式、状态模式和解释器模式2026/7/23第2章六大原则-13-本章目标了解设计模式的设计原则掌握单一职责原则的定义,并了解其体现及应用掌握里氏替换原则的定义,并了解其体现及应用掌握依赖倒置原则的定义,并了解其体现及应用掌握接口隔离原则的定义,并了解其体现及应用掌握迪米特法则的定义,并了解其体现及应用掌握开闭原则的定义,并了解其体现及应用-14-单一职责原则SingleResponsibilityPrinciple,SRP一个类应当只有一个引起变化的原因,即应当只有一个职责单一职责原则降低类的复杂性提高类的可读性提高代码的可维护性和复用性降低因变更引起的风险-15-单一职责原则的应用JavaEE中的分层框架模式实际上体现了单一职责原则将整个系统按照职责的内聚性分为不同的层,层内的模块与类具有宏观的内聚性,所关注的事情是一致的-16-里氏替换原则LiskovSubstitutionPrinciple,LSP所有引用基类的地方必须能透明的使用其子类对象继承的优点代码共享,减少类数量,每个子类都拥有父类的方法和属性提高代码的可重用性提高代码的可扩展性提高产品或项目的开放性继承的缺点继承是入侵式的。只要继承,就必须拥有父类的所有属性和方法降低代码的灵活性。子类必须拥有父类的属性和方法,受到限制增强了耦合性。当父类修改时,必须考虑子类的修改,这种修改可能造成大片的代码需要重构-17-里氏替换原则的应用里氏替换原则为良好的继承定义了规范,包含4层含义:
子类必须完全实现父类的方法;子类可以有自己的个性;覆盖或实现父类的方法时输入参数可以被放大;覆盖或实现父类的方法时输出结果可以被缩小。体现里氏替换原则的有如下几个模式:策略模式组合模式代理模式-18-依赖倒置原则-1DependenceInversionPrinciple,DIP包括三层含义:高层模块不应该依赖底层模块,两者都依赖其抽象抽象不依赖细节细节应该依赖于抽象-19-依赖倒置原则-2在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是具体的实现类,实现类实现了接口或继承了抽象类,其特点是可以直接被实例化依赖倒置原则在Java中的体现:模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生接口或抽象类不依赖于实现类实现类依赖于接口或抽象类依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性-20-依赖倒置原则的应用在项目中使用依赖倒置原则只要遵循以下几个规则:
每个类尽量都具有接口或抽象类,或者抽象类和接口两者都具备变量的表面类型尽量是接口或者是抽象类任何类都不应该从具体类派生尽量不要重写基类的方法结合里氏替换原则使用-21-接口隔离原则InterfaceSegregationPrinciple,ISP接口隔离原则有如下两种定义:客户端不应该依赖它不需要的接口;类间的依赖关系应该建立在最小的接口上接口隔离原则的具体的含义如下:一个类对另外一个类的依赖性应当是建立在最小的接口上的一个接口代表一个角色,不应当将不同的角色都交给一个接口。没有关系的接口合并在一起,形成一个臃肿的大接口,这是对角色和接口的污染。因此使用多个专门的接口比使用单一的总接口要好不应该强迫客户依赖于它们不用的方法。接口属于客户,不属于它所在的类层次结构。即不要强迫客户使用它们不用的方法,否则这些客户就会面临由于这些不使用的方法的改变所带来的改变-22-接口隔离原则的应用-23-迪米特法则LawofDemeter,LoD一个对象应当对其他对象尽可能少的了解迪米特法则具有代表性的表述:只与你直接的朋友们通信不要跟“陌生人”说话每一个软件单位对其他的单位都只有最少的了解,这些了解仅局限于那些与本单位密切相关的软件单位-24-迪米特法则的应用迪米特法则的核心观念就是类之间的解耦、弱耦合,只有弱耦合了以后,类的复用率才可以提高对迪米特法则进行应用的设计模式有:外观模式中介者模式-25-开闭原则Open-ClosedPrinciple,OCP个软件实体应当对扩展开放,对修改关闭在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。即应当可以在不必修改源代码的情况下改变这个模块的行为在面向对象的编程中,开闭原则是最基础的原则,其他原则都是开闭原则的具体形态开闭原则的作用:提高复用性提高可维护性提高灵活性易于测试-26-开闭原则的应用需求变更:
按照9折销售图书遵照“开闭原则”中对修改关闭的原则,不能直接修改IBook接口和NovelBook类,而是通过增加一个子类OffNovelBook来完成-27-小结-1单一职责原则SRP(SingleResponsibilityPrinciple):一个类,只有一个引起它变化的原因,应该只有一个职责单一职责原则提出一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计是否优良,但“职责”和“变化原因”都是不可度量的,因项目而异,因环境而异里氏替换原则LSP(LiskovSubstitutionPrinciple):所有引用基类的地方必须能透明地使用其子类对象,反之则不行在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则如果子类不能完整的实现父类的方法,或者父类的某些方法在子类中发生“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系替代继承-28-小结-2依赖倒置原则DIP(DependenceInversionPrinciple):高层模块不应该依赖底层模块,两者都应依赖其抽象;抽象不依赖细节;而细节依赖抽象依赖倒置原则在Java中的表现是:模块间的依赖通过抽象产生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生;接口或抽象类不依赖于实现类;实现类依赖接口或抽象类接口隔离原则ISP(InterfaceSegregationPrinciple):一个类对另外一个类地依赖性应当是建立在最小的接口上,使用多个专门的接口比使用单一的迪米特法则LoD(LawofDemeter):一个对象应该对其他对象有最少的了解,即一个类应该对自己一个类开闭原则OCP(Open-ClosePrinciple):一个软件实体如类、模块和函数应该对外扩展开放,对修改关闭第3章创建型模式-31-本章目标了解设计模式创建型分类掌握单例模式的特点及应用掌握工厂方法模式的特点及应用掌握抽象工厂模式的特点及应用掌握建造者模式的特点及应用掌握原型模式的特点及应用-32-创建型模式创建型模式(CreationalPattern)是对类的实例化过程的抽象化,能够提供对象的创建和管理职责。创建型模式共有5种:单例模式工厂方法模式抽象工厂模式建造者模式原型模式-33-单例模式SingletonPattern确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例在Java中实现单例模式两种形式:饿汉式单例类:类加载时,就进行对象实例化懒汉式单例类:第一次引用类时,才进行对象实例化饿汉式单例类与懒汉式单例类之间的区别:饿汉式在被加载时实例化,懒汉式在第一次引用时实例化从资源利用效率上说,饿汉式单例类要差一些,但从速度和反应时间角度来讲,则比懒汉式单例类稍好些饿汉式单例类可以在Java中实现,但不易在C++内实现。GoF在提出单例模式的概念时,举的例子是懒汉式的,他们的书影响之大,以致Java中单例类的例子也大多是懒汉式的。实际上,饿汉式单例类更符合Java语言本身的特点。-34-饿汉式单例publicclassSingleton{privatestaticSingletonm_instance=newSingleton();//构造方法私有,保证外界无法直接实例化
privateSingleton(){}//通过该方法获得实例对象
publicstaticSingletongetInstance(){returnm_instance;}}-35-懒汉式单例publicclassSingleton{privatestaticSingleton_instance;//构造方法私有,保证外界无法直接实例化
privateSingleton(){}//方法同步
synchronizedpublicstaticSingletongetInstance(){if(_instance==null){_instance=newSingleton();}return_instance;}}-36-单例模式的优缺点单例模式优点在内存中只有一个实例,减少了内存的开销只生成一个实例,所以减少了系统的性能开销避免对资源的多重占用可以在系统设置全局的访问点,优化和共享资源访问单例模式缺点无法创建子类,扩展困难对测试不利与单一职责原则有冲突-37-单例模式的应用场景和注意事项如果要求一个类有且仅有一个实例,当出现多个实例时就会造成不良反应,则此时可以采用单例模式要求生成唯一序列号的环境在整个项目中需要一个共享访问点或共享数据创建一个对象需要消耗的资源过多需要定义大量的静态常量和静态方法单例类可能具有状态,在使用时应注意以下两点:单例类仅局限于一个JVM,因此当多个JVM的分布式系统时,这个单例类就会在多个JVM中被实例化,造成多个单例对象的出现当两个类加载器同时加载同一个类时,会出现两个实例,此时也应尽量避免使用有状态的单例类反序列化克隆-38-单例模式的自然推广-多例模式多例模式特点有多个实例必须自己创建必须自己管理,对外界提供自己的实例多例模式分类:有上限多例模式无上限多例模式-39-工厂模式FactoryPattern工厂模式通常分为三种形式:简单工厂:对“开-闭”原则的支持不够,因为如果有新的产品加入到系统同中,则需要修改工厂类,将必要的逻辑加入到工厂类中工厂方法:可以用来允许系统在不修改具体工厂角色的情况下引进新的产品抽象工厂:最为抽象和最具有一般性,可以面对多个产品等级结构-40-工厂方法模式FactoryMethodPattern定义一个创建产品对象的工厂接口,将实际创建性工作推迟到子类中工厂方法模式涉及以下4个角色:
抽象工厂(Creator)角色:该角色是工厂方法模式的核心,与应用系统无关,任何在创建对象的工厂类必须实现这个接口。具体工厂(ConcreteCreator)角色:该角色实现了抽象工厂接口,含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。抽象产品(Product)角色:该角色负责定义产品的共性,实现对产品最抽象的定义。具体产品(ConcreteProduct)角色:该角色实现抽象产品角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。-41-工厂方法模式的优点和应用场景工厂方法模式的优点良好的封装性,代码结构清晰优秀的可扩展性屏蔽产品类工厂方法模式是典型的解耦框架工厂方法模式的应用场景new一个对象的替代品需要灵活的、可扩展的框架时工厂方法模式可以用在异构项目中工厂方法模式可以使用在测试驱动开发的框架下工厂方法模式实例publicinterfaceBenzFactory{ publicBenzcreateCar();}publicinterfaceBenz{ publicvoidcarColor(); publicvoidcarSpeed(); publicvoidcarPrice();}//BenzE260代码类似不详述publicclassBenzC180implementsBenz{publicBenzC180(){ this.carColor(); this.carSpeed(); this.carPrice();}publicvoidcarColor(){System.out.println("奔驰C180的颜色是银白色!");}publicvoidcarSpeed(){ System.out.println("奔驰C180的速度是280");}publicvoidcarPrice(){System.out.println("奔驰C180的价格是5块钱");}}publicclassC180FactoryimplementsBenzFactory{ @Override publicBenzcreateCar(){ returnnewBenzC180(); }}publicclassE260FactoryimplementsBenzFactory{ @Override publicBenzcreateCar(){ returnnewBenzE260(); }}publicclassCustomerDemo{publicstaticvoidmain(String[]args){ System.out.println("老板,给我介绍下C180!"); BenzFactorybenzFactory=newC180Factory(); benzFactory.createCar(); System.out.println("======================"); System.out.println("老板,给我介绍下E260!"); BenzFactorybenzFactory2=newE260Factory(); benzFactory2.createCar(); System.out.println("======================"); System.out.println("两辆车试驾完毕后,买了其中一辆离去……");}}-42--43-抽象工厂模式AbstractFactoryPattern为创建一组相关或相互依赖的对象提供一个接口,无需指定具体类抽象工厂的4个角色:抽象工厂(AbstractFactory)角色:该角色是抽象工厂模式的核心,与应用系统无关,任何创建对象的工厂类必须实现这个接口。具体工厂(ConcreteFactory)角色:该角色实现了抽象工厂接口,含有选择合适的产品对象的逻辑,并且受到应用程序的调用以创建产品对象。抽象产品(AbstractProduct)角色:该角色负责定义产品的共性,实现对产品最抽象的定义。具体产品(ConcreteProduct)角色:该角色实现抽象产品角色所声明的接口,抽象工厂模式所创建的任何产品对象都是某个具体产品角色的实例-44-抽象工厂模式的优缺点和应用场景抽象工厂模式的优点产品族内的约束为非公开状态生产线的扩展非常容易抽象工厂模式的应用场景当一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式抽象工厂模式的缺点产品族本身的扩展非常困难,如果需要在产品族中增加一个新的产品类型,则需要修改多个接口,并且会影响已有的工厂类-45-抽象工厂模式实例-1//英雄生产抽象工厂publicinterfaceIHeroFactory{//获得力量型英雄publicIStrengthHerogetStrengthHero();//获得敏捷型英雄publicIAgileHerogetAgileHero();//获得智力型英雄publicIIntellectualHerogetIntellectualHero();}//近卫军团工厂publicclassSentinelFactoryimplementsIHeroFactory{@OverridepublicIStrengthHerogetStrengthHero(){//TODOAuto-generatedmethodstubreturnnewStrengHero("流浪剑客");}@OverridepublicIAgileHerogetAgileHero(){//TODOAuto-generatedmethodstubreturnnewAgileHero("剑圣");}@OverridepublicIIntellectualHerogetIntellectualHero(){//TODOAuto-generatedmethodstubreturnnewIntellectualHero("仙女龙");}}//天灾军团工厂publicclassScourgeFactoryimplementsIHeroFactory{@OverridepublicIStrengthHerogetStrengthHero(){//TODOAuto-generatedmethodstubreturnnewStrengHero("斧王");}@OverridepublicIAgileHerogetAgileHero(){//TODOAuto-generatedmethodstubreturnnewAgileHero("影魔");}@OverridepublicIIntellectualHerogetIntellectualHero(){//TODOAuto-generatedmethodstubreturnnewIntellectualHero("召唤师");}}-46-抽象工厂模式实例-2//力量英雄
//其他类型代码类似不再详述publicinterfaceIStrengthHero{ publicvoidcreateHero();}publicclassStrengHeroimplementsIStrengthHero{privateStringname;publicStrengHero(Stringname){super();=name;}@OverridepublicvoidcreateHero(){//TODOAuto-generatedmethodstubSystem.out.println("创建力量型英雄:"
+name);}}publicclassHeroDemo{publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubIHeroFactorysentinelFactory=newSentinelFactory();//创建近卫工厂IStrengthHerosentineStrengthHero=sentinelFactory.getStrengthHero();IAgileHerosentineAgileHero=sentinelFactory.getAgileHero();IIntellectualHerosentineIntellectualHero=sentinelFactory.getIntellectualHero();System.out.println("近卫军团:");sentineStrengthHero.createHero();sentineAgileHero.createHero();sentineIntellectualHero.createHero();IHeroFactoryscourgeFactory=newScourgeFactory();//创建天灾工厂IStrengthHeroscourgeStrengthHero=scourgeFactory.getStrengthHero();IAgileHeroscourgeAgileHero=scourgeFactory.getAgileHero();IIntellectualHeroscourgeIntellectualHero=scourgeFactory.getIntellectualHero();System.out.println("天灾军团:");scourgeStrengthHero.createHero();scourgeAgileHero.createHero();scourgeIntellectualHero.createHero();}}-47-建造者模式BuilderPattern将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示建造者模式的4个角色:抽象建造者(Builder)角色:该角色用于规范产品的各个组成部分,并进行抽象,一般独立于应用程序的逻辑。具体建造者(ConcreteBuilder)角色:该角色实现抽象建造者中定义的所有方法,并且返回一个组建好的产品实例。产品(Product)角色:该角色是建造中的复杂对象,一个系统中会有多于一个的产品类,这些产品类并不一定有共同的接口,完全可以是不相关联的。导演者(Director)角色:该角色负责安排已有模块的顺序,然后告诉Builder开始建造。-48-建造者模式的优缺点和应用场景建造者模式的优点封装性,使用建造者模式可以使客户端不必知道产品内部组成的细节建造者独立,容易扩展便于控制细节风险,由于具体的建造者是独立的,因此可以对建造过程,逐步细化,而不对其他的模块产生任何影响建造者模式的应用场景相同的方法,不同的执行顺序,产生不同的结果时多个部件都可以装配到一个对象中,产生的运行结果又不相同时产品类非常复杂,其方法调用顺序不同产生了不同的效能时在对象创建过程中会使用到系统的一些其他对象,这些对象在产品对象的创建过程中不易得到时-49-建造者模式实例-50-原型模式PrototypePattern用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象原型模式3个角色:客户(Client)角色:该角色提出创建对象的请求。抽象原型(Prototype)角色:该角色是一个抽象角色,通常由一个Java接口或抽象类实现,给出所有的具体原型类所需的接口。具体原型(ConcretePrototype)角色:该角色是被复制的对象,必须实现抽象原型接口。-51-使用克隆实现原型模式Java中内置了克隆机制,Object类具有一个clone()方法,能够实现对象的克隆使一个类支持克隆需要两步:实现Cloneable接口覆盖Object的clone()方法,完成对象的克隆操作,通常只需调用Object的clone()方法即可。为了使外部能够调用此类的clone()方法,可以将可访问性修改为publicpublicinterfacePrototypeextendsCloneable{ //克隆方法
Prototypeclone();}publicclassConcretePrototypeimplementsPrototype{ publicPrototypeclone(){ try{ return(Prototype)super.clone(); }catch(CloneNotSupportedExceptione){ e.printStackTrace(); returnnull; } }}publicclassClient{ publicvoidoperation(Prototypeexample){ //得到example的副本
Prototypep=example.clone(); }}-52-原型模式的优点和应用场景原型模式的优点性能优良:原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好,特别是在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点逃避构造函数的约束:这既是优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,因此减少了约束,需要在实际应用时进行权衡考虑原型模式的应用场景资源优化场景,类初始化需要消化非常多的资源时性能和安全要求的场景,通过new产生一个对象需要非常繁琐的数据准备或访问权限时一个对象多个修改者的场景,一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用-53-小结单例模式(Singleton)一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式减少内存开支,避免对资源的多重占用,优化和共享源访问;但单例模式扩展难,不易测试工厂方法模式(FactoryMethod)定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中抽象工厂模式(AbstractFactory)是工厂方法的升级,为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类建造者模式(Builder)也叫生成器模式,将一个复杂对象的构建与其表示分类,使得同样的构建过程可以创建不同的表示原型模式(Prototype)用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象第4章结构型模式-56-本章目标了解设计模式中结构型分类掌握代理模式的特点及应用掌握装饰模式的特点及应用掌握配置器模式的特点及应用掌握桥梁模式的特点及应用掌握外观模式的特点及应用掌握享元模式的特点及应用-57-结构型模式结构型模式(StructuralPattern)描述如何将类或者对象结合在一起形成更大的结构。结构型模式的目的是通过组合类或对象产生更大结构以适应更高层次的逻辑需求。结构型模式共有7种:代理模式装饰模式适配器模式组合模式桥梁模式外观模式享元模式-58-代理模式ProxyPattern为其他对象提供一种代理以控制对这个对象的访问代理模式3个角色:抽象主题(Subject)角色:该角色是真实主题和代理主题的共同接口,以便在任何可以使用真实主题的地方都可以使用代理主题。代理主题(ProxySubject)角色:也叫做委托类、代理类,该角色负责控制对真实主题的引用,负责在需要的时候创建或删除真实主题对象,并且在真实主题角色处理完毕前后做预处理和善后处理工作。真实主题(RealSubject)角色:该角色也叫做被委托角色、被代理角色,是业务逻辑的具体执行者。-59-代理模式的种类远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局部代表对象。这个不同的地址空间可以是在本机器中,也可在另一台机器中。虚拟(Virtual)代理:有时需要创建一些消耗较多资源的对象,可以首先创建代理对象,而将真实对象的创建延迟。例如加载一个很大的图片,可以通过图片的代理来代替真正的图片。保护(ProtectorAccess)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。缓存(Cache)代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。同步(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。智能引用(SmartReference)代理:当一个对象被引用时,提供一些额外的操作,例如记录访问的流量和次数等。-60-代理模式的优点和应用场景代理模式的优点职责清晰,真实的角色实现实际的业务逻辑,不用关心其他非本职的事务,通过后期的代理完成附加的事务,附带的结果就是编程简洁清晰。高扩展性,具体主题角色随需求不同可能有很多种,但只要实现了接口,代理类就完全可以在不做任何修改的情况下代理各种真实主题角色。智能化,代理类可以在运行时才确定需要去代理的真实主题,这是一种强大的功能。代理模式的应用场景代理模式应用非常广泛,大到一个系统框架、企业平台,小到事务处理、代码片段,随处可见代理模式的使用,例如JavaRMI的远程调用就是一种代理模式的应用,现在流行的AOP也可以通过代理模式实现-61-代理模式实例publicinterfaceIBuyTicket{publicvoidlogin();//登录系统publicvoidstation(Stringstart,Stringend);//选择车票起始终点站publicvoidvalidate();//身份校验publicvoidpayMoney();//付款}publicclassTicketBuyerimplementsIBuyTicket{privateStringname;publicTicketBuyer(Stringname){=name;}publicvoidlogin(){//TODOAuto-generatedmethodstubSystem.out.println(+"登录12306火车票购票系统>>>>>>");}publicvoidstation(Stringstart,Stringend){//TODOAuto-generatedmethodstubSystem.out.println(+"选择了火车票的起始站点:"
+start+"\t终点站点:"
+end);}publicvoidvalidate(){//TODOAuto-generatedmethodstubSystem.out.println(+"通过了身份验证!");}publicvoidpayMoney(){//TODOAuto-generatedmethodstubSystem.out.println(+"抢到了火车票并进行了付款操作!");}}publicclassTicketProxyimplementsIBuyTicket{privateIBuyTicketbuyer;publicTicketProxy(IBuyTicketbuyer){this.buyer=buyer;}@Overridepublicvoidlogin(){//TODOAuto-generatedmethodstubthis.buyer.login();;}@Overridepublicvoidstation(Stringstart,Stringend){//TODOAuto-generatedmethodstubthis.buyer.station(start,end);}@Overridepublicvoidvalidate(){//TODOAuto-generatedmethodstubthis.buyer.validate();}@OverridepublicvoidpayMoney(){//TODOAuto-generatedmethodstubthis.buyer.payMoney();}}publicclassTicketDemo{publicstaticvoidmain(String[]args){IBuyTicketbuyTicket=newTicketBuyer("王小贱");TicketProxyproxy=newTicketProxy(buyTicket);proxy.login();proxy.station("青岛","北京");proxy.validate();proxy.payMoney();}}-62-装饰模式DecoratorPattern动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活装饰模式的4个角色:抽象构件(Component)角色:该角色用于规范需要装饰的对象(原始对象)。具体构件(ConcreteComponent)角色:该角色实现抽象构件接口,定义一个需要装饰的原始类。装饰(Decorator)角色:该角色持有一个构件对象的实例,并定义一个与抽象构件接口一致的接口。具体装饰(ConcreteDecorator)角色:该角色负责对构件对象进行装饰。-63-装饰模式的优缺点和应用场景装饰模式的优点装饰类和被装饰类可以独立发展,而不会相互耦合装饰模式是继承关系的一个替代方案装饰模式可以动态地扩展一个实现类的功能装饰模式的应用场景需要扩展一个类的功能,或给一个类增加附加功能。需要动态地给一个对象增加功能,这些功能可以再动态地撤销。需要为一批类进行改装或加装功能。装饰模式的缺点多层的装饰是比较复杂的装饰模式是对继承的有力补充。单纯使用继承时,在一些情况下就会增加很多子类,而且灵活性差,维护也不容易。装饰模式可以替代继承,解决类膨胀的问题,如Java基础类库中的输入输出流相关的类大量使用了装饰模式-64-装饰模式实例//汽车接口publicinterfaceICar{//车的装配publicvoidshow();}//奔驰E260车(裸车,需要装饰)publicclassBenzE260implementsICar{publicvoidshow(){System.out.println("奔驰E260车无导航仪,无行车记录仪,内室原装......");}}//汽车装饰(抽象装饰)publicabstractclassCarDecoratorimplementsICar{privateICarcar=null;publicCarDecorator(ICarcar){this.car=car;}publicvoidshow(){this.car.show();}}//具体汽车装饰publicclassConcreteCarDecoratorextendsCarDecorator{publicConcreteCarDecorator(ICarcar){super(car);}//给车安装行车记录仪privatevoidsetGrapher(){System.out.println("安装高清大容量带夜视的行车记录仪......");}//给车安装GPS设备privatevoidsetGps(){System.out.println("安装最顶级的GPS定位导航系统......");}//给车铺上坐垫并贴上警示语privatevoidsetCushion(){System.out.println("铺上HelloKitty的坐垫,然后在后车玻璃贴上警示语标签,表明自己是新手......");}//重写show方法publicvoidshow(){super.show();this.setGrapher();this.setGps();this.setCushion();}}publicclassOrnamentDemo{publicstaticvoidmain(Stringargs[]){ICarcar=newBenzE260();//对奔驰车进行装饰CarDecoratordecorat=newConcreteCarDecorator(car);decorat.show();}}-65-适配器模式AdapterPattern将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作适配器模式3个角色:目标(Target)角色:该角色定义要转换成的目标接口。源(Adaptee)角色:需要被转换成目标角色的源角色。适配器(Adapter)角色:该角色是适配器模式的核心,其职责是通过继承或是类关联的方式,将源角色转换为目标角色。-66-适配器模式的优点和应用场景适配器模式的优点适配器模式可以让两个没有任何关系的类在一起运行。增加了类的透明性。提高类的复用度。增强代码的灵活性。适配器模式的应用场景修改一个已经投产中的系统时,需要对系统进行扩展,此时使用一个已有的类,但这个类不符合系统中的接口,这时使用适配器模式是最合适的,它可以将不符合系统接口的类进行转换,转换成符合系统接口的、可以使用的类-67-适配器模式实例publicclassChinese{publicStringspeakChinese(){return"你好,美女!可以一起吃个饭吗?";}}publicinterfaceIEnglish{publicvoidspeakEnglish();}publicclassTranslateAdapterextendsChineseimplementsIEnglish{@OverridepublicvoidspeakEnglish(){Stringspeak=speakChinese();System.out.println("对【"+speak+"】进行翻译中......");System.out.println("Hello,beauty!Canyoueatamealtogether?");}}publicclassTranslateDemo{publicstaticvoidmain(String[]args){IEnglishenglish=newTranslateAdapter();english.speakEnglish();}}-68-组合模式CompositePattern将对象组合成树形结构以表示“部分—整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性组合模式的角色:抽象构件(Component)角色:该角色定义参加组合对象的共有方法和属性,规范一些默认的行为接口。叶子构件(Leaf)角色:该角色是叶子对象,其下没有其他的分支,定义出参加组合的原始对象的行为。树枝构件(Composite)角色:该角色代表参加组合的、其下有分支的树枝对象,它的作用是将树枝和叶子组合成一个树形结构,并定义出管理子对象的方法,如add()、remove()等。-69-组合模式的优缺点和应用场景组合模式的优点高层模块调用简单节点可自由增加组合模式的应用场景需要描述对象的部分和整体的等级结构需要客户端忽略个体构件和组合构件的区别,平等的对待所有的构件组合模式的缺点不易控制树枝构件的类型不易使用继承的方法来增加新的行为Java基础类库的swing部分中就大量使用了组合模式,大部分控件都是JComponent的子类,同时其add()方法又可向界面添加JComponent类型的控件,从而使得使用者可以以统一的方式操作各种控件-70-组合模式实例publicinterfaceCompany{//获取信息
publicStringgetInfo();}//树枝节点类publicclassConcreteCompanyimplementsCompany{privateArrayList<Company>companyList=newArrayList<Company>();privateStringname;//姓名privateStringsex;//性别privateStringposition;//职位privateintsalary;//薪水//构造函数publicConcreteCompany(Stringname,Stringsex,Stringposition,intsalary){=name;this.sex=sex;this.position=position;this.salary=salary;}publicvoidadd(Companycompany){panyList.add(company);}publicvoidremove(Companycompany){panyList.remove(company);}publicArrayList<Company>getChild(){returnpanyList;}publicStringgetInfo(){Stringinfo="";info="名称:"
+;info=info+"\t性别:"
+this.sex;info=info+"\t职位:"
+this.position;info=info+"\t薪水:"+this.salary;returninfo;}}//叶子节点类publicclassEmployeeimplementsCompany{privateStringname;//姓名privateStringsex;//性别privateStringposition;//职位privateintsalary;//薪水//构造函数publicEmployee(Stringname,Stringsex,Stringposition,intsalary){=name;this.sex=sex;this.position=position;this.salary=salary;}publicStringgetInfo(){Stringinfo="";info="名称:"
+;info=info+"\t性别:"
+this.sex;info=info+"\t职位:"
+this.position;info=info+"\t薪水:"+this.salary;returninfo;}}publicclassClientDemo{publicstaticvoidmain(Stringargs[]){//CEOConcreteCompanyroot=newConcreteCompany("王小贱","男","CEO",100000);//部门经理ConcreteCompanydevelopDep=newConcreteCompany("郑能亮","男","研发部经理",12000);//部门员工Employeee1=newEmployee("A","男","研发部",3000);……//生成树root.add(developDep);……//显示公司层次System.out.println(root.getInfo());display(root);}//遍历树(递归)publicstaticvoiddisplay(ConcreteCompanyroot){for(Companyc:root.getChild()){if(cinstanceofEmployee){//如果节点类型是叶子节点System.out.println(c.getInfo());}else{//树枝节点System.out.println("\n"+c.getInfo());display((ConcreteCompany)c);//递归调用}}}}-71-桥梁模式BridgePattern将抽象和实现解耦,使得两者可以独立地变化桥梁模式涉及的角色:抽象化(Abstraction)角色:该角色抽象化给出的定义,并保存一个对实现化对象的引用。实现化(Implementor)角色:该角色给出实现化角色的接口,但不给出具体的实现。修正抽象化(RefinedAbstraction)角色:该角色扩展抽象化角色,它引用实现化角色并对抽象化角色进行修正。具体实现化(ConcreteImplementor)角色:该角色对实现化角色接口中的方法进行具体实现。-72-桥梁模式的优缺点和应用场景桥梁模式的优点抽象和实现分离实现对客户透明,客户端不用关心细节的实现提高灵活性和扩展性桥梁模式的应用场景如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系。设计要求实现化角色的任何改变不应当影响客户端,或者说实现化角色的改变对客户端是完全透明的。一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态耦合。不希望或不适合使用继承的场合。继承具有强入侵性质,即父类有的方法,子类必须有;而桥梁模式是弱关联关系。因此对于比较明确不发生变化的,则可以通过继承完成;若不能确定是否会发生变化,则通过桥梁模式来解决。-73-桥梁模式实例publicabstractclassNoodle{ISeasoningseasoning;publicNoodle(ISeasoningseasoning){this.seasoning=seasoning;}//获得面条publicabstractStringgetNoodle();}//调味品、佐料接口publicinterfaceISeasoning{//添加调味品、佐料publicStringaddSeasoning();}//拉面类publicclassRamenNoodlesextendsNoodle{publicRamenNoodles(ISeasoningseasoning){super(seasoning);//TODOAuto-generatedconstructorstub}@OverridepublicStringgetNoodle(){//TODOAuto-generatedmethodstubreturnseasoning.addSeasoning()+"的拉面"
;}}//刀削面类publicclassSlicedNoodlesextendsNoodle{publicSlicedNoodles(ISeasoningseasoning){super(seasoning);//TODOAuto-generatedconstructorstub}@OverridepublicStringgetNoodle(){returnseasoning.addSeasoning()+"的刀削面";}}publicclassPepperimplementsISeasoning{@OverridepublicStringaddSeasoning(){//TODOAuto-generatedmethodstubreturn"放上点儿辣椒";}}publicclassVinegarimplementsISeasoning{@OverridepublicStringaddSeasoning(){//TODOAuto-generatedmethodstubreturn"放上点儿醋";}}publicclassEatNoodleDemo{publicstaticvoidmain(String[]args){ISeasoningpepper=newPepper();RamenNoodlesramenNoodle=newRamenNoodles(pepper);ISeasoningvinegear=newVinegar();SlicedNoodlesslicedNoodle=newSlicedNoodles(vinegear);System.out.println("王小贱吃的是:"
+ramenNoodle.getNoodle());System.out.println("王恩吃的是:"
+slicedNoodle.getNoodle());}}-74-外观模式FacadePattern要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。外观模式提供一个高层次的接口,使得子系统更易使用外观模式:外观(Facade)角色:客户端可以调用该角色的方法,该角色知晓相关子系统的功能和责任。正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去,即该角色没有实际的业务逻辑,只是一个委托类。子系统(subsystem)角色:可以同时有一个或多个子系统,每一个子系统都不是一个单独的类,而是一个类的集合。子系统不知道外观角色的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已。-75-外观模式的优缺点和应用场景外观模式的优点减少系统的相互依赖,所有的依赖都是对Facade对象的依赖,与子系统无关。提高灵活性,不管子系统内部如何变化,只要不影响Facade对象,任何活动都是自由的。提高安全性,Facade中未提供的方法,外界就无法访问,提高系统的安全性。外观模式的应用场景为一个复杂的模块或子系统提供一个供外界访问的接口。子系统相对独立,外界对子系统的访问只要黑箱操作即可。预防风险扩散,使用Facade进行访问操作控制。-76-外观模式实例//机场publicclassAirport{publicvoidbookTicket(Stringfrom,Stringto){System.out.println("订购了从"
+from+"到"
+to+"的机票");}}//酒店publicclassHotel{publicvoidbookRoom(intdays){System.out.println("订了"
+days+"天的房间");}}//司机publicclassChauffeur{publicvoiddrive(Stringto){System.out.println("司机开车去"
+to);}}//秘书publicclassSecretary{privateChauffeurchauffeur=newChauffeur();privateHotelhotel=newHotel();privateAirportairport=newAirport();//安排出差publicvoidtravel(Stringto,intdays){airport.bookTicket("青岛",to);chauffeur.drive("机场");hotel.bookRoom(days);}}publicclassBoss{publicstaticvoidmain(String[]args){Secretarysecretary=newSecretary();System.out.println("老板告诉秘书要到美国出差10天");("美国",10);}}-77-享元模式FlyweightPattern使用共享对象可有效地支持大量的细粒度的对象。是池技术的重要实现方式,可以降低大量重复的、细粒度类的内存开销享元对象区分内部状态(InternalState)和外部状态(ExternalState):内部状态是存储在享元对象内部的、可以共享的信息,并且不会随环境改变而改变。外部状态是随环境改变而改变且不可以共享的状态。享元对象的外部状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。享元模式的角色:抽象享元(Flyweight)角色:该角色对享元类进行抽象。具体享元(ConcreteFlyweight)角色:该角色实现抽象享元定义的业务。享元工厂(FlyweightFactory)角色:该角色就是构造一个池容器,负责创建和管理享元角色,并提供从池容器中获得对象的方法,保证享元对象可以被系统适当的共享。客户端(Client)角色:该角色需要自行存储所有享元对象的外部状态。-78-享元模式的优缺点和应用场景享元模式的优点大幅减少内存中对象的数量,降低程序内存的占用,提高性能享元模式的缺点享元模式增加了系统的复杂性,需要分出外部状态和内部状态,而且内部状态具有固化特性,不应该随外部状态改变而改变,这使得程序的逻辑复杂化。享元模式将享元对象的状态外部化,而读取外部状态使得运行时间变长。享元模式的应用场景系统中有大量的相似的对象,这些对象耗费大量的内存。细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,即对象没有特定身份。需要缓冲池的场景。-79-享元模式实例//抽奖奖票publicinterfaceIPrize{publicvoidLuckDraw(Stringresult);}publicclassPrizeFlyweightimplementsIPrize{//奖品内部状态privateStringprizeName;publicPrizeFlyweight(StringprizeName){this.prizeName=prizeName;}@OverridepublicvoidLuckDraw(Str
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 丽水市2025浙江丽水市人民政府办公室下属事业单位选聘2人笔试历年参考题库典型考点附带答案详解
- 中山市2025广东中山市横栏镇人民政府所属事业单位招聘事业单位人员13人笔试历年参考题库典型考点附带答案详解
- 上海市2025上海复旦大学发展研究院技术创新战略研究中心招聘主任助理1名笔试历年参考题库典型考点附带答案详解
- 2026青海海东市平安驿文化旅游有限公司招聘1人笔试历年典型考点题库附带答案详解
- 2026西南计算机有限责任公司招聘18人笔试历年常考点试题专练附带答案详解
- 2026福建福州市江南智慧城市建设运营有限公司招聘10人笔试历年备考题库附带答案详解
- 2026湖北西陵城市发展集团有限公司面向社会招聘5人笔试历年备考题库附带答案详解
- 2026浙江舟山市水务集团有限公司企业员工招聘3人笔试历年备考题库附带答案详解
- 2026年检验科安全操作规程
- 2026年幼儿园中秋节集体活动方案
- 铁路四电项目施工组织设计已上传
- 2025年度《血管导管相关感染预防与控制指南(2025版)》培训试题附答案
- 安全基础知识培训资料课件
- 医院领导带班管理制度
- CJ/T 136-2007给水衬塑复合钢管
- 营造林工勤岗技师考试题库及答案
- T/CCIAS 009-2023减盐酱油
- (试卷)2024年广东省初中学业水平考试·物理
- GB/T 3163-2024真空技术术语
- 困难职工帮扶管理制度
- 肿瘤伤口护理
评论
0/150
提交评论