版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
面向对象的技术与方法共129页第2页设计模式实践导论设计模式理论典型设计模式实例分析使用设计模式的指导共129页第3页导论什么是模式?有一些问题及其解决方案不断变换面孔重复出现,在这些不同的面孔后面是共同的本质;这些共同的本质就是模式(Pattern)共129页第4页导论设计面向对象软件比较困难,而设计可复用的面向对象软件就更加困难。
A设计过程
B设计要求
共129页第5页导论新手一般需要花费较长时间领会良好的面向对象设计?有经验的设计者显然知道一些新手所不知道的东西,这又是为什么呢?内行的设计者知道:不是解决任何问题都要从头做起!共129页第6页导论将面向对象软件的设计经验作为设计模式记录下来。每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计。共129页第7页什么是设计模式ChristopherAlexander说过:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”,
-----主要指城市和建筑模式。他的思想也同样适用于面向对象设计模式,只是在面向对象的解决方案里,我们用对象和接口代替了墙壁和门窗。两类模式的核心都在于提供了相关问题的解决方案。共129页第8页设计模式带给我们?使我们可以更加简单方便地复用成功的设计和体系结构。将已证实的技术表述成设计模式也会使我们更加容易理解其设计思路。共129页第9页设计模式带给我们?设计模式帮助我们做出有利于系统复用的选择,避免设计损害了系统复用性。通过提供一个显式类和对象作用关系以及它们之间潜在联系的说明规范,设计模式甚至能够提高已有系统的文档管理和系统维护的有效性。简而言之,设计模式可以帮助设计者更快更好地完成系统设计。共129页第10页理解模式设计模式其实就是面向对象原则的活用,尤其是多态特性,往往成为大多数模式的核心。
1.设计模式对于专家和初学者都同样有用。学习设计模式有助于更好地把握面向对象的思想
2.许多凭经验而直觉感受到的东西,其实暗合设计模式的思想。共129页第11页设计模式与语言设计模式建立于面向对象理论基础之上,所以,要实现某种具体的设计模式,一般需要使用某种具体的面向对象语言,如Java和C++,但其思想则可能可以用非面向对象的语言如C来实现.共129页第12页模式的四个基本要素1.模式的名称(patternname)
用来描述模式的问题、解决方案和效果。好处:增加了我们的设计词汇,帮助我们思考,便于我们与其他人交流设计思想及设计结果。共129页第13页2.该模式所能解决的问题(problem)
描述了应该在何时使用模式主要内容:它解释了设计问题和问题存在的前因后果,它可能描述了特定的设计问题,如怎样用对象表示算法等。也可能描述了导致不灵活设计的类或对象结构。有时候,问题部分会包括使用模式必须满足的一系列先决条件。模式的四个基本要素共129页第14页3.解决方案(solution)
描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。模式类似模板,可应用于多种不同场合。所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决这个问题。模式的四个基本要素共129页第15页4.使用该模式的结果(consequences)
描述了模式应用的效果及使用模式应权衡的问题。
1)时间和空间的衡量
2)对系统的灵活性、扩充性或可移植性的影响模式的四个基本要素共129页第16页小结一个设计模式命名、抽象和确定了一个通用设计结构的主要方面,这些设计结构能被用来构造可复用的面向对象设计。设计模式确定了所包含的类和实例,它们的角色、协作方式以及职责分配。每一个设计模式都集中于一个特定的面向对象设计问题或设计要点,描述了什么时候使用它,在另一些设计约束条件下是否还能使用,以及使用的效果和如何取舍。共129页第17页小结理解隐藏在设计模式背后的面向对象设计原则和设计理念:
设计模式最根本的意图是适应需求变化(封装变化)针对接口编程,而不要针对实现编程优先使用聚合,而不是继承设计模式三要素:
特定领域,问题,解决方案共129页第18页参考数目GoF的经典著作《设计模式》Gamma,Helm和Johnson,Vlissides简称GangofFour(四人帮)HeadFirst设计模式,中国电力出版社共129页第19页设计模式实例认识最基本的设计模式使用设计模式共129页第20页Singleton模式最简单的设计模式特点:在任何时候都只能创建一个类的实例只此一家,别无分号共129页第21页Singleton模式结构共129页第22页Singleton模式实现共129页第23页Singleton模式实现共129页第24页Singleton模式的要点1.隐藏默认类的构造函数2.添加一个共享的成员,以引用单独的,实例化的对象3.创建一个公有函数来创建或返回被引用的对象共129页第25页使用Singleton模式适用场景: 1.某个软件组件需要访问数据库,为此,可能希望整个组件只创建一个数据库连接
2.整个系统的主控类,一般只能创建一个.共129页第26页Singleton模式优缺点Singleton模式是做为"全局变量"的替代品出现的。所以它具有全局变量的特点:全局可见、贯穿应用程序的整个生命期,它也具有全局变量不具备的性质:同类型的对象实例只可能有一个。共129页第27页Factory模式问题:1、子类对象的实例化(子类名称)2、具体创建哪个子类对象不确定共129页第28页Factory模式Factory模式的两个最重要的功能:1)定义创建对象的接口,封装了对象的创建;2)使得具体化类的工作延迟到了子类中。共129页第29页Factory模式在第一个问题中,我们经常就是声明一个创建对象的接口,并封装了对象的创建过程。Factory这里类似于一个真正意义上的工厂(生产对象)。专门定义一个类来负责创建其它类的实例,被创建的实例通常都具有共同的父类。SimpleFactory模式。共129页第30页Factory模式SimpleFactory模式结构示意图1:共129页第31页SimpleFactory模式先定义水果(Fruit)接口:classFruit{public:virtualvoidplant()=0;//水果是被种植的virtualvoidenableEat()=0;//水果能吃}
共129页第32页SimpleFactory模式苹果(Apple)是水果(Fruit)的子类:classApple:publicFruit{public:voidplant(){System.out.println("种苹果!");}voidenableEat(){System.out.println(“苹果好吃!”);}}共129页第33页SimpleFactory模式
葡萄(Grape)是水果(Fruit)的子类:classGrape:publicFruit{voidplant(){System.out.println("种葡萄!");}voidenableEat(){System.out.println(“葡萄好吃!”);}}共129页第34页SimpleFactory模式鸭梨(Pear)是水果(Fruit)的子类:
classPear:publicFruit{voidplant(){System.out.println("种鸭梨!");}voidenableEat(){System.out.println(“鸭梨好吃!”);}}共129页第35页SimpleFactory模式定义买水果(BuyFruit)这一过程类:classBuyFruit{/*简单工厂方法*/Fruit*buyFruit(Stringwhich){if(which.equalsIgnoreCase("apple")){//如果是苹果,则返回苹果实例returnnewApple();}共129页第36页SimpleFactory模式elseif(which.equalsIgnoreCase("pear")){//如果是鸭梨,则返回鸭梨实例returnnewPear();}elseif(which.equalsIgnoreCase("grape")){//如果是葡萄,则返回葡萄实例returnnewGrape();}else{returnnull;}}}共129页第37页SimpleFactory模式测试类:voidmain(){//开始买水果这个过程BuyFruitbuy=newBuyFruit();buy.buyFruit(“apple”).enableEat();//调用苹果的enableEat()方法}}共129页第38页SimpleFactory模式说明:A:我要购买苹果,只需向工厂角色(BuyFruit)请求即可。而工厂角色在接到请求后,会自行判断创建和提供哪一个产品。
B:但是对于工厂角色(BuyFruit)来说,增加新的产品(比如说增加草莓)就是一个痛苦的过程。工厂角色必须知道每一种产品,如何创建它们,以及何时向客户端提供它们。换言之,接纳新的产品意味着修改这个工厂。共129页第39页SimpleFactory模式C:因此SimpleFactory模式的开放性比较差。有什么办法可以解决这个问题吗?共129页第40页Factory模式在第二个问题中,我们需要提供一个对象创建对象的接口,并在子类中提供其具体实现(因为只有在子类中可以决定到底实例化哪一个类)。将对象的创建交由父类中定义的一个标准方法来完成,而不是其构造函数,究竟应该创建何种对象由具体的子类负责决定。
Factorymethod模式。共129页第41页FactoryMethod模式目的:定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。共129页第42页FactoryMethod模式结构共129页第43页FactoryMethod模式适用性:当一个类不知道它所必须创建的对象的类的时候。当一个类希望由它的子类来指定它所创建的对象的时候。当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理着这一信息局部化的时候。共129页第44页FactoryMethod模式1、同上定义水果接口,各类水果对接口进行相应实现。2、将买水果(BuyFruit)定义为接口类:classBuyFruit{/*简单工厂方法*/virtualFruit*buyFruit()=0;}共129页第45页FactoryMethod模式买苹果是(BuyApple)对买水果(BuyFruit)接口的实现
classBuyApple:publicBuyFruit{Fruit*buyFruit(){returnnewApple();//返回苹果实例}}
共129页第46页FactoryMethod模式买鸭梨是(BuyPear)对买水果(BuyFruit)接口的实现
classBuyPear:publicBuyFruit{Fruit*buyFruit(){returnnewPear();//返回鸭梨实例}}共129页第47页FactoryMethod模式
买葡萄是(BuyGrape)对买水果(BuyFruit)接口的实现classBuyGrape:publicBuyFruit{Fruit*buyFruit(){returnnewGrape();//返回葡萄实例}}
共129页第48页FactoryMethod模式测试类:voidmain(){BuyApple*buy=newBuyApple();//开始买水果这个过程(buy->buyFruit())->enableEat();//调用苹果的enableEat()方法}共129页第49页FactoryMethod模式说明:A:工厂方法模式和简单工厂模式在结构上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。工厂方法模式可以允许很多具体工厂类从抽象工厂类中将创建行为继承下来,从而可以成为多个简单工厂模式的综合,进而推广了简单工厂模式。
共129页第50页FactoryMethod模式B:工厂方法模式退化后可以变得很像简单工厂模式。设想如果确定一个系统只需要一个具体工厂类,那么就不妨把抽象工厂类合并到具体的工厂类中去。由于反正只有一个具体工厂类,所以不妨将工厂方法改成为静态方法,这时候就得到了简单工厂模式。
共129页第51页FactoryMethod模式C:如果需要加入一类新的水果,那么只需要加入一个新的水果类以及它所对应的工厂类。没有必要修改客户端,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色。对于增加新的水果类而言,这个系统完全支持“开-闭”原则。
共129页第52页FactoryMethod模式D:对FactoryMethod模式而言,它只是针对一种类别(如本例中的水果类Fruit),但如果我们还想买肉,那就不行了,这时就必须要AbstractFactory模式帮忙了。
共129页第53页AbstractFactory模式目的:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。基本结构:共129页第54页AbstractFactory模式共129页第55页AbstractFactory模式同样,我们先定义水果(Fruit)接口,并根据各类水果具体实现接口定义肉(Meat)接口:classMeat{voidfeed()=0;//肉是喂养的voidenableEat()=0;//肉能吃}
共129页第56页AbstractFactory模式猪肉(PigMeat)是对肉(Meat)接口的实现:classPigMeat:publicMeat{voidfeed(){System.out.println("养猪!");}voidenableEat(){System.out.println(“猪肉好吃!”);}}共129页第57页AbstractFactory模式牛肉(CowMeat)是对肉(Meat)接口的实现:classCowMeat:publicMeat{voidfeed(){System.out.println("养牛!");}voidenableEat(){System.out.println(“牛肉好吃!”);}}
共129页第58页AbstractFactory模式可以定义买货人(Buyer)接口:classBuyer{/*买水果工厂方法*/Fruit*buyFruit(FruitwhichFruit)=0;/*买肉的工厂方法*/Meat*buyMeat(MeatwhichMeat)=0;}
共129页第59页AbstractFactory模式我(MyBuyer)是对买货人(Buyer)接口的实现:
classMyBuyer:publicBuyer{/*买水果工厂方法*/Fruit*buyFruit(FruitwhichFruit){returnwhichFruit;}/*买肉的工厂方法*/Meat*buyMeat(MeatwhichMeat){returnwhichMeat;}}
共129页第60页AbstractFactory模式测试类:
voidmain(){Fruit*apple=newApple();//苹果实例Meat*pig=newPigMeat();//猪肉实例
共129页第61页AbstractFactory模式MyBuyermy=newMyBuyer();//我是买者的实例my->buyFruit(apple)->enableEat();//我买苹果my->buyMeat(pig)->enableEat();//我买猪肉}共129页第62页AbstractFactory模式说明:
A:抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多个产品族中的产品对象。这就是抽象工厂模式的用意。B:抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。
共129页第63页AbstractFactory模式C:抽象工厂模式与工厂方法模式的最大区别就在于,工厂方法模式针对的是一个产品(Fruit)等级结构;而抽象工厂模式则需要面对多个产品等级结构(Fruit、Meat)。
共129页第64页AbstractFactory模式适用性:在以下情况可以使用AbstractFactory模式一个系统要独立于它的产品的创建、组合和表示时。一个系统要由多个产品系列中的一个来配置时。当你要强调一系列相关的产品对象的设计以便进行联合使用时。当你提供一个产品类库,而只想显示它们的接口而不是实现时。65Pizza连锁店1,顾客可以根据菜单点Pizza2,Pizza的种类不同3,每个店的Pizza根据地区不同风味不同4,给出每个店可以自己加入一些秘方5,比萨制作过程:准备,烘烤,切边,装盒6,请给出关键方法和客户代码的实现66想想下面的代码有什么问题676869真正有压力的是要增加新的pizza种类70封装对象的创建717273讨论74757677练习787980专卖店想加入自己的一些秘方81828384共129页第85页Factory模式的注意事项不要盲目地用Factory来创建对象,只有在对象种类有可能在未来增加的情况之下才使用!Factory用复杂性来实现灵活性,但同时降低了可阅读性所以:模式是把双刃剑,要用得适当!共129页第86页Adapter模式问题:实际生活中Adapter模式解决的问题软件系统设计和开发中的问题共129页第87页Adapter模式目的:将一个类(Adaptee,被适配者)的接口转换成客户希望的另外一个接口(适配接口)。用户实现适配接口的类叫适配器(Adaptor),也叫做,包装器(Wrapper)。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。实现:类适配器使用多重继承对一个接口与另一个接口进行匹配;对象适配器依赖于对象组合。共129页第88页Adapter模式类适配器结构(使用多重继承)共129页第89页Adapter模式使用C++实现类适配器
Adapter类采用公共方式继承Target类,用私有方式继承Adaptee类。共129页第90页Adapter模式示例代码:classAdaptee//classAdaptee{public:
voidSpecialRequest(){}};classTarget//classTarget{public:
virtualvoidRequest()=0;};共129页第91页Adapter模式
//classAdapter
classAdapter:publicTarget,privateAdaptee
{
public:
virtualvoidRequest(){SpecialRequest();}
};
共129页第92页Adapter模式客户端代码:
Target*p=newAdapter();
p->Request();//实际上调用的是Adaptee::SpecialRequest()
共129页第93页Adapter模式对象适配器结构(依赖于对象组合)共129页第94页Adapter模式使用C++实现对象适配器
Adapter类采用公共方式继承Target类,将Adaptee类对象作为自己的私有成员变量。共129页第95页Adapter模式示例代码:classAdaptee//classAdaptee{public:
voidSpecialRequest(){}};classTarget//classTarget{public:
virtualvoidRequest()=0;};共129页第96页Adapter模式
//classAdapter
classAdapter:publicTarget
{
public:
virtualvoidRequest(){_adaptee.SpecialRequest();}
private:
Adaptee_adaptee;
};
共129页第97页Adapter模式客户端代码:
Target*p=newAdapter();
p->Request();//实际上调用的是Adaptee::SpecialRequest()
98例子:动物图形编辑器我们的程序现成的程序重用Dogdraw()Catdraw()Tookitdraw()Fishdraw()99策略1-对象适配器适配器采用对象复合Dogdraw()Catdraw()Tookitdraw()Fishdraw()theTiger.paint();TigerAdaptordraw()Tigerpaint()+theTiger100//这是个适配器程序,适配Tiger使其具有Tookit的接口publicclassTigerAdaptorimplementsTookit{publicTigertheTiger;publicTigerAdaptor(Tigert){ theTiger=t;}publicvoiddraw(){ theTiger.paint();}}101策略2-类适配器适配器采用类继承Dogdraw()Catdraw()Tookitdraw()Fishdraw()super.paint();Tigerpaint()TigerAdaptor1draw()102publicclassTigerAdaptor1extendsTigerimplementsTookit{publicTigerAdaptor1(){}
publicvoiddraw(){ super.paint();}}共129页第103页Adapter模式实现方式:接口继承:通过继承,子类获得了父类的接口实现继承:通过继承子类获得了父类的实现,并不统一接口共129页第104页Adapter模式适用性:你想使用一个已经存在的类,而它的接口不符合你的需求。你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。(仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。共129页第105页Adapter模式和其他很多模式一样,学习设计模式的重点是学习每种模式的思想,而不应拘泥于它的某种具体结构图和实现。因为模式是灵活的,其实现可以是千变万化的,只是所谓万变不离其宗。在STL中大量运用了Adapter模式,象functionadapter、iteratoradapter,它们与这里说的adapter结构并不一样,但思想是一样的。共129页第106页Adapter模式STL示例:基于双端队列(deque)的堆栈(stack)stack的类定义:templateclass<_Container=deque<_Ty>>classstack{//LIFOqueueimplementedwithacontainer
protected:_Containerc;//theunderlyingcontainer
public:
typedef_Containercontainer_type;
typedeftypename_Container::value_typevalue_type;
typedeftypename_Container::size_typesize_type;共129页第107页Adapter模式stack():c(){//constructwithemptycontainer}stack(const_Container&_Cont):c(_Cont){//constructbycopyingspecifiedcontainer}共129页第108页Adapter模式boolempty()const{//testifstackisempty
return(c.empty());}size_typesize()const{//testlengthofstack
return(c.size());}共129页第109页Adapter模式value_type&top(){//returnlastelementofmutablestack
return(c.back());}constvalue_type&top()const{//returnlastelementofnonmutablestack
return(c.back());}共129页第110页Adapter模式voidpush(constvalue_type&_Val){//insertelementatend
c.push_back(_Val);}voidpop(){//eraselastelementc.pop_back();}共129页第111页Adapter模式bool_Eq(conststack<_Ty,_Container>&_Right)const{//testforstackequality
return(c==_Right.c);}bool_Lt(conststack<_Ty,_Container>&_Right)const{//testifthis<_Rightforstacks
return(c<_Right.c);}};共129页第112页Adapter模式说明:
关键之处在于_Containerc,stack所有的操作都转交给c去处理了。(这实际上就是前面所说的"objectadapter")
共129页第113页Adapter模式stack的使用方法很简单,例如:
intia[]={1,3,2,4};
dequeid(ia,ia+4);
stackis(id);
共129页第114页Bridge模式问题:
面向对象分析和设计:一是松耦合(Coupling),二是高内聚(Cohension)。面向对象系统追求的目标就是尽可能地提高系统模块内部的内聚(Cohesion)、尽可能降低模块间的耦合(Coupling)。但是……共129页第115页Bridge模式OO系统的开发过程中遇到这样的问题:客户给了你一个需求,于是使用一个类来实现(A);客户需求变化,有两个算法实现功能,于是改变设计,我们通过一个抽象的基类,再定义两个具体类实现两个不同的算法(A1和A2);共129页第116页Bridge模式客户又告诉我们说对于不同的操作系统,于是再抽象一个层次,作为一个抽象基类
A0,再分别为每个操作系统派生具体类(A00和A01,其中A00表示原来的类A)实现不同操作系统上的客户需求,这样我们就有了一共4个类。可能用户的需求又有变化,比如说又有了一种新的算法……..
我们陷入了一个需求变化的郁闷当中,也因此带来了类的迅速膨胀。
???共129页第117页Bridge模式目的:将抽象部分与它的实现部分分离,使它们都可以独立地变化。提出动机:当一个抽象可能有多个实现时,通常用继承来协调它们。抽象类定义对该抽象的接口,而具体的子类则用不同方式加以实现。
但是此方法有时不够灵活。共129页第118页Bridge模式结构:共129页第119页Bridge模式示例代码:classImplementor//classImplementor{
public:
virtualvoidOperationImp()=0;};//classConcreteImplementorAclassConcreteImplementorA:publicImplementor{
public:
virtualvoidOperationImp(){}
};共129页第120页Bridge模式//classConcreteImplementorBclassConcreteImplementorB:publicImplementor{
public:
virtualvoidOperationImp(){}};classAbstraction//classAbstraction{public:
voidOperation(Implementor*imp){assert(imp);imp->OperationImp();}};
共129页第121页Bridge模式客户端代码:
Abstractionobj;
Implementor*impa=newConcreteImplementorA();
Implementor*impb=newCon
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 深度解析(2026)《GBT 33516-2017LZG型鼓形齿式联轴器》(2026年)深度解析
- 临时支架设计与检算技术
- 网络安全渗透测试与防护 课件17.Metasploit 框架之专用扫描模块
- 医疗数据安全治理框架与实践
- 医疗数据安全技术路线的共识机制评估
- 医疗数据安全成熟度:区块链能力图谱
- 胸痛病人分诊流程图课件
- 医疗数据安全区块链智能预警系统
- 安徽省潜山市第二中学2026届高二上数学期末达标检测模拟试题含解析
- 胆道疾病解剖课件
- 人工智能与创业智慧(北京林业大学)学习通网课章节测试答案
- 浪浪山小妖怪开学第一课课件
- 五金厂生产部工时统计制度
- 研磨钻石的专业知识培训课件
- 以青春之名赴时代之约-高中爱国主题班会-2025-2026高中主题班会
- 2025年传达学习医疗机构重大事故隐患判定清单会议记录
- 桂林学院《新时代中国特色社会主义与实践》2024-2025学年第一学期期末试卷
- 企业无违规经营声明范本模版
- 2025年医疗器械直调申请表
- 道桥模拟考试题与答案
- 2025至2030中国家用燃气报警器市场现状发展分析及发展战略规划报告
评论
0/150
提交评论