第五章创建型设计模式_第1页
第五章创建型设计模式_第2页
第五章创建型设计模式_第3页
第五章创建型设计模式_第4页
第五章创建型设计模式_第5页
已阅读5页,还剩84页未读 继续免费阅读

下载本文档

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

文档简介

1、第五章创建型设计模式返回目录l目录l5.1 工厂模式l5.2 抽象工厂模式l5.3 建造者模式l5.4 单件模式l5.5 原型模式返回目录5.1 工厂(Factory method)模式l一、工厂模式的由来l二、工厂模式的意图及实用性l三、工厂模式的结构及参与者l四、应用举例l五、效果分析返回目录5.1.1 工厂模式的由来l 在面向对象编程中, 很普遍的方法是用一个new操作符产生一个对象实例,就是用来构造对象实例的。classAP1Class classA private P1 p1 public classA() p1=new P1(); 返回目录new操作符直接生成对象会带来一些问题l首

2、先,要使用new运算符创建一个对象我们l而这有时候并不现实,譬如打开一个视频文件需要一个播放器对象,但是用户可能不知道具体播放器叫什么名字,而只需要系统分派给这个视频文件一个合适的播放器,这种情况下用new运算符是不适宜的; 返回目录5.1.1 工厂模式的由来-new操作符直接生成对象会带来一些问题l其次,许多类型对象的: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象。 l在这些情况, 新对象的建立就是一个 “过程”,不仅是一个操作。那么如何能轻松方便地完成这些复杂的对象创建工作,这就引入了工厂模式。 返回目录5.1.1

3、工厂模式的由来-new操作符直接生成对象会带来一些问题classAP1Class Factory public P1 getP1() private P1 p1; p1=new P1(); return p1; FactoryClass classA private P1 p1; private Factory f; public classA() f=new Factory(); p1=f.getP1(); 解决方法将new操作移交给第三方类Factory返回目录5.1.2 工厂模式的结构返回目录5.1.3 工厂模式的参与者1)IProduct 定义工厂方法所创建的对象的接口。2)Concr

4、eteProduct (productA, productB) 实现Product接口3)IFactory 声明工厂方法,该方法返回一个Product类型的对象。 IFactory也可以定义一个工厂方法的缺省实现,它返回一个缺省的ConcreteProduct对象。 可以调用工厂方法以创建一个Product对象。4)ConcreteFactory (productAFactory, productBFactory ) 重定义工厂方法已返回一个ConcreteProduct实例。返回目录5.1.4 应用举例l 现在我们考虑一个日志记录的例子,假定我们要设计日志记录的类,支持记录的方法有FileL

5、og和EventLog两种方式。 ClientLogFileLogEventLog返回目录同学们的常见做法public class clientpublic static void Main(string args) Log log; log=new FileLog(); Log.write();New返回目录用工厂模式解决日志问题client LogFactoryFileFactoryEventFactoryLogFileLogEventLogNew返回目录5.1.4 应用举例 1234public abstract class LogFactory56 public abstract Lo

6、g Create();7l 4public class EventFactory:LogFactory 5 6 public override EventLog Create() 7 8 return new EventLog(); 9 1014public class FileFactory:LogFactory1516 public override FileLog Create()17 18 return new FileLog();19 20返回目录5.1.4 应用举例l 客户端程序代码:l 4public class client 5 6 public static void Mai

7、n(string args) 7 8 LogFactory factory = new EventFactory(); 910 Log log = factory.Create();1112 log.Write();13 1415public class clientpublic static void Main(string args) Log log; log=new EventLog(); Log.write;对比之前的代码返回目录5.1.4 应用举例l 在客户程序中,我们有效地避免了具体产品对象和应用程序之间的耦合,可是我们也看到,增加了具体工厂对象和应用程序之间的耦合。那这样究竟带来

8、什么好处呢?我们知道,在应用程序中,Log对象的创建是频繁的,在这里我们可以把l LogFactory factory = new EventFactory();l 这句话放在一个中,任何需要用到Log对象的地方仍然不变。要是换一种日志记录方式,只要修改一处为:l LogFactory factory = new FileFactory();l 其余的任何地方我们都不需要去修改。有人会说那还是修改代码,其实在开发中我们很难避免修改,但是我们可以尽量做到只修改一处。Visual studio返回目录5.1.5 效果分析l1用工厂方法在一个类的内部创建对象通常比直接创建对象更灵活。l2Factor

9、y Method模式通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,较好的解决了这种紧耦合的关系。返回目录l目录l5.1 工厂模式l5.2 抽象工厂模式l5.3 建造者模式l5.4 单件模式l5.5 原型模式返回目录5.2 抽象工厂(Abstract Factory)模式一、抽象工厂模式的由来二、抽象工厂模式的意图及适用性三、抽象工厂模式的结构及参与者四、应用举例五、效果分析返回目录5.2.1抽象工厂模式的由来l 我们在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作,同时由于需求的变化,这“一系列相互依赖的对象”也要改变,如何应对这种变化呢?

10、如何像工厂方法模式一样绕过常规的new,然后提供一种“封装机制”来避免客户程序和这种“”的紧耦合?可能有人会说,你也可以将这些对象一个一个通过工厂方法模式来解决呀?但是,我们试想,既然是一系列相互依赖的对象,它们是有联系的,每个对象都这样解决,你又如何来保证他们的联系呢? 返回目录简单工厂与抽象工厂的区别简单工厂抽象工厂返回目录5.2.1抽象工厂模式的由来l举一个例子:Windows桌面主题,当你更换一个桌面主题的时候,系统的开始按钮、任务栏、菜单栏、工具栏等等都变了,而且是一起变的,他们的色调都还很一致,难道类似这样的问题,怎么来解决呢?它的答案就是抽象工厂模式。 返回目录5.2.2 抽象工

11、厂模式的意图和适用性意图:一种创建型模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。返回目录5.2.2 模式的意图和适用性适用性:以下情况可以使用Abstract Factory模式:1. 一个系统要独立于它的产品的创建、组合和表示时。2.一个系统要由多个产品系列中的一个来配置时。3.当你要强调一系列相关的产品对象的设计以便进行联合时。4.当你提供一个产品类库,而只想显示它们的接口而不是实现时。 返回目录5.2.3抽象工厂模式的结构及参与者抽象工厂模式的结构返回目录5.2.3抽象工厂模式的结构及参与者返回目录5.2.3 抽象工厂模式的结构及参与者Abstract Fa

12、ctory模式中主要参与者:1) Abstract Factory:声明一个创建抽象产品对象的操作接口。2) ConcreteFactory(ProductFactory1,):实现创建具体对象的操作。3)Abstract Product:为一类产品对象声明一个接口。4) ConcreteProduct:定义一个将被相应的具体工厂创建的产品对象(实现 Abstract Product )。5) Client:仅使用由AbstractFactory和AbstractProduct类声明的接口。返回目录5.2.4 应用举例l简单的例子: 假设你需要设计一个花园的布局。 花园有三种风格:典雅型、实用

13、型和懒人型。 花园中有3个位置需要种植植物:花台、墙角和花园中心。 返回目录一种简单的花园设计风格/位置花台中心墙角典雅型郁金香榕树兰草实用型葡萄石榴丝瓜懒人型月季茶花竹子至结构图返回目录实现情况返回目录5.2.5 效果分析l分离了具体的类l使得易于交换产品系列l有利于产品的一致性l难以支持新种类的产品返回目录更多的抽象工厂例子返回目录抽象工厂抽象工厂1 支持多种视感支持多种视感(look-and-feel)标准的用户界面工具包标准的用户界面工具包WidgetFactorycreateScrollBar()createWindow()MACWidgetFactoryMSWidgetFactor

14、ycreateScrollBar()createWindow()ClientWindowMACWindowMACScrollBar两种不同风格两种不同风格: MAC MSMSWindowScrollBarcreateScrollBar()createWindow()MSScrollBarMS风格风格返回目录抽象工厂抽象工厂2:不同类型电脑生产不同类型电脑生产ComputerProducercreateCPU()createRAM()MacProducerPcProducercreateCPU()createRAM()createCPU()createRAM()ClientInterfaceCP

15、UInterfaceRAMPcCPUMacCPUPcRAMMacRAM返回目录抽象工厂抽象工厂3:制菜抽象工厂的结构图制菜抽象工厂的结构图 制菜工厂制菜工厂做蔬菜做蔬菜()做荤菜做荤菜()川菜制作工厂川菜制作工厂沪菜制作工厂沪菜制作工厂做蔬菜做蔬菜()做荤菜做荤菜()做蔬菜做蔬菜()做荤菜做荤菜() 顾客顾客蔬菜类蔬菜类肉类肉类 土豆土豆青菜青菜牛肉牛肉鸡肉鸡肉返回目录抽象工厂抽象工厂4 :Abstract Factory 设计模式在设计模式在Java API中的应用中的应用Java中的中的java.awt.Toolkit抽象类运用了抽象类运用了Abstract Factory设计模式设计模式

16、ButtonPeer implementation 3ImagePeer implementation 3ToolKitcreateButton()createImage()ConcreteToolKit1ConcreteToolKit2ConcreteToolKit3ButtonPeerImagePeercreateButton()createImage()createButton()createImage()createButton()createImage()ButtonPeer类类: 包含了平包含了平台相关的代码,以产生台相关的代码,以产生可视按钮化可视按钮化返回目录l目录l5.1 工

17、厂模式l5.2 抽象工厂模式l5.3 建造者模式l5.4 单件模式l5.5 原型模式返回目录5.3 建造者(Builder)模式一、建造者模式的由来二、建造者模式的意图及适用性三、建造者模式的结构四、应用举例五、效果分析返回目录5.3.1 建造者模式的由来l 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;l 这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。返回目录建造者、简单工厂与抽象工厂的区别简单工厂抽象工厂建造者子对象返回目录5.3.1 建造者模式的由来l 在实际生活中,也有这样的例子:l 譬如一个房屋的构

18、建。创建过程基本不变,但是门窗等组件却是易变的。过程不变,组件变化抽象工厂模式基本没有创建过程,组件创建的顺序随机麦当劳的套餐就是抽象工厂模式返回目录5.3.1 建造者模式的由来l 如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?这就是要说的建造者模式。 封装过程,隔离变化的部分返回目录5.3.2 建造者模式的意图和适用性l模式的意图 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。返回目录5.3.2 建造者模式的意图和适用性l以下情况可以使用建造者模式:l1. 。l2. 创建复杂对象的

19、算法稳定,或建造者模式可以强迫生成一定的顺序。l3. 当构造过程允许被构造的对象有不同的表示时。返回目录5.3.3 建造者模式的结构和参与者l建造者模式结构图返回目录协作协作客户创建客户创建Director对象,并用它所想要的对象,并用它所想要的Builder对象进行配置。对象进行配置。一旦产品部件被生成,导向器就会通知生成器。一旦产品部件被生成,导向器就会通知生成器。生成器处理导向器的请求,并将部件添加到该产品中。生成器处理导向器的请求,并将部件添加到该产品中。客户从生成器中检索产品。客户从生成器中检索产品。aClientaDirectoraConcreteBuildernew Concre

20、teBuildernew Director(aConcreteBuilder)construct()buildPartA()buildPartB()getResult()product:Product返回目录首先需要一个接口,它定义如何创建复杂对象的各个部件首先需要一个接口,它定义如何创建复杂对象的各个部件: public interface Builder /创建部件创建部件A 比如创建汽车车轮比如创建汽车车轮void buildPartA(); /创建部件创建部件B 比如创建汽车方向盘比如创建汽车方向盘void buildPartB(); /创建部件创建部件C 比如创建汽车发动机比如创建汽

21、车发动机void buildPartC(); /返回最后组装成品结果返回最后组装成品结果 (返回最后装配好的汽车返回最后装配好的汽车)/成品的组装过程不在这里进行成品的组装过程不在这里进行,而是转移到下面的而是转移到下面的Director类中进行类中进行/从而实现了解耦从而实现了解耦过程过程和和部件部件Product getResult(); public class Director private Builder builder; public Director( Builder builder ) this.builder = builder; / 将部件将部件partA partB p

22、artC最后组成复杂对象最后组成复杂对象/这里是将车轮这里是将车轮 方向盘和发动机组装成汽车的过程方向盘和发动机组装成汽车的过程public void construct() builder.buildPartA();builder.buildPartB();builder.buildPartC(); public class ConcreteBuilder implements Builder Part partA, partB, partC; public void buildPartA() /这里是具体如何构建这里是具体如何构建partA的代码的代码 public void buildP

23、artB() /这里是具体如何构建这里是具体如何构建partB的代码的代码 public void buildPartC() /这里是具体如何构建这里是具体如何构建partB的代码的代码 public Product getResult() /返回最后组装成品结果返回最后组装成品结果 public class Product public interface Part Builder builder = new ConcreteBuilder();Director director = new Director( builder ); director.construct(); Product

24、 product = builder.getResult(); 123Client:返回目录更详细的建造者模式结构图返回目录5.3.3 建造者模式的结构和参与者1)Builder 为创建一个Product对象的各个部件指定抽象接口。2)ConcreteBuilder 实现Builder的接口以构造和装配该产品的各个部件。 定义并明确它所创建的表示。 提供一个检索产品的接口3)Director 构造一个使用Builder接口的对象。4)Product 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。 包含定义组成部件的类,包括将这些部件装配成最终产品的

25、接口。返回目录5.3.4 应用举例l设计游戏场景中的房屋l假设房屋由五个部分组成:地板、墙壁、窗户、门和天花板。l构建一个房屋的步骤是一定的,而具体的组件(门、窗等)是易变的。l采用建造者模式分离易变组件和稳定的构建过程。返回目录5.3.4 应用举例l public abstract class House/定义一个房屋抽象类l l public abstract class Builder/这一部分是易变的l l public abstract void BuildFloor();/地板l public abstract void BuildDoor();/门l public abstrac

26、t void BuildWindows();/窗户l public abstract void BuildWall();/墙壁l public abstract void BuildHouseCeiling()/天花板l public abstract House GetHouse();l 返回目录5.3.4 应用举例l public abstract class GameManager/这一部分的方法是稳定的l l public static House CreateHouse(Builder builder)l l builder.BuildFloor();l builder.BuildD

27、oor();l builder.Buildwall();l builder.BuildWindows();l builder.BuildHouseCeiling();l return builder.GetHouse();l l l 返回目录5.3.4 应用举例l public class RomanHouse : Housel l l l public class RomanHouseBuilder : Builderl l public override void BuildDoor()l l public override void BuildFloor()l l public over

28、ride void BuildWindows()l l public override void BuildWall()l l public override void BuildHouseCeiling()l l public override RomanHouse GetHouse()l l 返回目录应用举例l class Appl l public static void main()l l House house =l GameManager.CreateHouse(new RomanHouseBuilder();l l 返回目录House RomanHouseBuilderRoman

29、HouseBuilderGameManagerAppclass App public static void main() House house = GameManager.CreateHouse(new RomanHouseBuilder(); 建造者模式的产品一般不需要抽象类director返回目录 RomanHouseBuilderRomanHouseBuilderGameManagerAppclass App public static void main() House house = GameManager.CreateHouse(new RomanHouseBuilder();

30、 取消掉抽象类后director返回目录思考:如何实现过程不变,组件变化?思考:如何实现过程不变,组件变化? RomanHouseBuilderRomanHouseBuilderGameManagerAppclass App public static void main() House house = GameManager.CreateHouse(new RomanHouseBuilder(); 取消掉抽象类后director返回目录思考:如何实现过程不变,组件变化? RomanHouseBuilderRomanHouseBuilderGameManagerAppclass App pub

31、lic static void main() House house = GameManager.CreateHouse(new RomanHouseBuilder(); director HouseBHouseBdoor1door2window1window2返回目录5.3.5 效果分析l1. 建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。l2. 每一个Builder都相对独立,而与其它的Builder无关。l3. 可使对构造过程更加精细控制。l4. 将构建代码和表示代码分开。l5. 建造者模式的缺点在于难于应付“分步骤构建算法”的需

32、求变动。返回目录返回目录l目录l5.1 工厂模式l5.2 抽象工厂模式l5.3 建造者模式l5.4 单件模式l5.5 原型模式返回目录5.4 单件(Singleton)模式一、单件模式的由来二、单件模式的意图及适用性三、单件模式的结构及参与者四、应用举例五、效果分析返回目录5.4.1 单件模式的由来l每台计算机可以有若干个打印机,但只能有一个 Printer Spooler,避免两个打印作业同时输出到打 印机。 lPC机中可能有几个串口,但只能有一个COM1口的 实例。 返回目录5.4.1 单件模式的由来l系统中只能有一个窗口管理器。l系统中只能有一个文件系统。l一个数字滤波器只能有一个A/D

33、转换齐。l一个会计系统只能专用于一个公司。返回目录 我们怎么样才能保证一个类只有一个实例并且这个实例易于被访问呢?一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象。 一个更好的办法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建(通过截取创建新对象的请求),并且它可以提供一个访问该实例的方法。这就是Singleton模式。5.4.1 单件模式的由来返回目录5.4.2 单件模式的意图和适用性l模式的意图 保证一个类仅有一个实例,并提供一个访问它的全局访问点。返回目录5.4.2 单件模式的意图适用性l在下面的两种情况下均可使用Singleton模式:l当类只能

34、有一个实例而且用户可以从一个众所周知的访问点访问它时。l当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。返回目录5.4.3 单件模式的结构和参与者l单件模式结构图UML结构图参与者说明Client 创建或调用这个单件实例的客户端。Sigleton 被调用的单件对象。返回目录5.4.3 单件模式的结构和参与者Singletonl 定义一个Instance操作,允许客户访问它的唯一实例。Instance是一个类操作(即C+中的一个静态成员函数) 。l 可能负责创建它自己的唯一实例。返回目录5.4.4 应用举例 美国总统的职位是Singleton,美国宪法规

35、定了总统的选举,任期以及继任的顺序。这样,在任何时刻只能由一个现任的总统。无论现任总统的身份为何,其头衔美利坚合众国总统是访问这个职位的人的一个全局的访问点。 返回目录Class Singleton /单件模式的定义public:static Singleton* Instance(); /客户通过该成员函数访问单件protected:Singleton(); /构造函数为受保护型,直接实例化将出错private:static Singleton* _instance; /指向本身的一个唯一实例的指针;5.4.4 应用举例返回目录相应的实现是Singleton * Singleton:_ins

36、tance = 0; /初始化类成员Singleton* Singleton:Instance()If(_instance = 0)_instance =new Singleton; /如果成员变量为0,则唯 /一实例化return _instance;5.4.4 应用举例返回目录思考:l单例模式的加锁问题l单例模式的其他实现方法?lSpring的单例模式返回目录5.4.5 效果分析l对唯一实例的受控访问因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它。l缩小名空间Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染名空间。l

37、允许对操作和表示的精化Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。你可以用你所需要的类的实例在运行时刻配置应用。返回目录l允许可变数目的实例这个模式使得你易于改变你的想法,并允许Singleton类的多个实例。此外,你可以用相同的方法来控制应用所使用的实例的数目。只有允许访问Singleton实例的操作需要改变。l比类操作更灵活另一种封装单件功能的方式是使用类操作(即C+中的静态成员函数或者是Smalltalk中的类方法)。但这两种语言技术都难以改变设计以允许一个类有多个实例。此外,C+中的静态成员函数不是虚函数,因此子类不能多态的重定义它们。5.4.5 效

38、果分析返回目录5.5 原型(prototype)模式l一、原型模式的由来l二、原型模式的意图及适用性l三、原型模式的结构及参与者l四、应用举例l五、效果分析返回目录5.5.1 原型模式的由来l在软件系统中,客户希望创建一个类对象(产品)时,可能有三种情况:l知道产品具体型号-使用new运算符创建l不知道型号,知道特定的需求-使用工厂模式l不知道需求,但想要一个和已知对象相同的对象-使用原型模式返回目录5.5.1 原型模式的意图和适用性l 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 返回目录5.1.2 原型模式的意图和适用性l在下列情况下,应当使用Prototype模式:l

39、1当一个系统应该独立于它的产品创建,构成和表示时;l2当要实例化的类是在运行时刻指定时,例如,通过动态装载;l3为了避免创建一个与产品类层次平行的工厂类层次时;返回目录5.1.2 原型模式的结构和参与者返回目录5.1.2 原型模式的结构和参与者1)客户(Client)角色:客户端类向原型管理器提出创建对象的请求。2)抽象原型(Prototype)角色:它是对各种具体原型的抽象,通常由一个C#接口或抽象类实现。3)具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。4)原型管理器(Prototype Manager)角色:创建具体原型类的

40、对象,并记录每一个被创建的对象。返回目录5.1.3 应用举例l假定我们要开发一个调色板,用户单击调色板上任一个方块,将会返回一个对应的颜色的实例,下面我们看看如何通过原型模式来达到系统动态加载具体产品的目的。l很自然,我们利用OO的思想,把每一种颜色作为一个对象,并为他们抽象出一个公用的父类,如下图:返回目录5.1.3 应用举例返回目录5.1.3 应用举例l再来看看使用原型模式开发调色板的结构图:返回目录5.1.3 应用举例lpublic abstract class Color /定义颜色抽象类llpublic abstract void Display();llpublic class R

41、edColor:Color /具体的颜色,红色llpublic override void Display()llConsole.WriteLine(Reds RGB Values are:255,0,0);lllpublic class GreenColor:Color /具体的颜色,绿色llpublic override void Display()llConsole.WriteLine(Greens RGB Values are:0,255,0);ll返回目录5.1.3 应用举例labstract class ColorPrototype/抽象的原型llpublic abstract ColorPrototype Clone();llclass ConcteteColorPrototype : ColorPrototype/具体的原型llprivate int _red, _green, _blue;lpublic ConcteteColorPrototype(int red, int green, int blue)/构造函数llthis._red = red;lthis._green =

温馨提示

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

评论

0/150

提交评论