Head First 学习笔记
- 格式:docx
- 大小:1.51 MB
- 文档页数:34
⼀句话的事⼉,Headfirst设计模式head first 设计模式,是⽐较有趣的⼀本设计模式的书。
在学校⾥看书和在⼯作时看书,意义是不⼀样的。
在学校时是为读书⽽读书,我们可以从0到1,我们有的是时间。
但是⼯作后就不⼀样。
我觉得这时的书更像是打通⾃⼰任督⼆脉的武功秘诀。
在平时⼯作中,杂七杂⼋地学了⼀些东西,但是却不能融会贯通。
所以还需要通过书来厘清你的思路。
这是写本⽂的出发点,也是我的碎碎念!看完该书后,转换成⾃⼰的语⾔,再表达出来,可能有错(那是⼀定的),但是,有总⽐没有好。
如果有同学能够从中得到些启发,也算是⾃⼰的⼀种幸运吧!我竟试图以⼀句话来描述⼀个设计模式!1. 策略模式!将统⼀的东西作为基类,可变的东西⾏为独⽴出来,在基类中通过变量进⾏引⽤,通过委托变量的⽅式,使⽤setter⽅法将委托变量改变,使其具有⾏为可变性。
⾯向接⼝编程,⽽⾮⾯向类编程。
其好处是,⽤同样的接⼝,通过不同⾏为类的传⼊产⽣不同的效果,便以改变⾏为变得容易。
2. 观察者模式!类似于发布-订阅模式。
存在注册服务,通知的过程。
其实现⽅式可以理解为,注册服务时,将观察者加⼊到队列当中,当主题发⽣变更时,由主题主动依次从观察者队列中依次调⽤,从⽽达到通知主动推送的作⽤。
其好处是,观察者随时注册观察可以实时收到消息,⽽被观察者对此⼀⽆所知,从⽽在达到通知的同时也解藕了。
3. 装饰者模式!以某对象为主要对象,⽣成后,将其传⼊装饰者构造函数中,经过装饰后,再⾏输出的模式。
该模式,可以许多散乱的⽅法独⽴组装出来,⽽不会影响其他变化,该模式是通过继承来实现的。
典型的装饰者模式运⽤,java io 类的继承,有多个主类,及多个装饰类,从⽽⽅便⽤户操作想要的⽅法。
其好处是,在⼤⽅向不变的情况下,可以反复更改主要的⾏为结果,对于⼀些附加类的变化,可以很⽅便地通过该模式进⾏数据再加⼯。
4. ⼯⼚模式!分为简单⼯⼚模式-⼯⼚模式-抽象⼯⼚模式。
英语单词Redundance: 冗余,多余Intentional:故意的,企图的,策划的stuff[stʌf]n.材料, 原料; 物品, 东西; 木料; 纺织品v.塞满, 填充, 填满; 饱食, 吃得过多indented[in·dent·ed || ɪn'dentɪd]adj.锯齿状的; 受契约约束的; 缩进排印的blown1[bləʊn]adj.喘气的; 被苍蝇弄赃的; 精疲力竭的; 有蝇卵附着的; 吹制的blown (blow)2[bləʊn]v.吹, 刮; 随风飘动; 吹动; 吹响, 鸣响; 吹; 吹掉; 吹动; 刮走; 使开花; 开blow[bləʊ]n.吹动, 吹气; 吹牛, 自夸; 强风, 暴风#一击, 殴打; 不幸; 打击; 精神上的打击#开花v.吹, 刮; 随风飘动; 吹动; 吹响, 鸣响; 吹; 吹掉; 吹动; 刮走; 使开花; 开full blown完全成熟的; 具有一切特征的; 充分发展的scratch[skrætʃ]v.抓, 搔(痒), 划破, 划掉n.抓痕, 乱写,抓的声音, 起跑线adj.无让步的tricky['triki]adj.棘手的, 狡猾的, 巧妙的shrink[ʃrɪŋk]n.收缩, 畏缩, 萎缩v.收缩, 萎缩, 退缩; 使收缩, 使缩小appropriate[ap·pro·pri·ate || ə'prəʊprɪət]v.拨出; 挪用, 盗用; 占用adj.适当的, 恰当的, 相称的pickle ['pikl]n.腌汁, 泡菜, <英口>淘气鬼, <口>困境v.腌, 泡comprehend[com·pre·hend || ‚kɒmprɪ'hend]v.领会; 包括; 理解duplicate[du·pli·cate || 'djuːplɪkət]n.副本, 复制品, 复本adj.复制的, 二重的v.复制; 影印, 拷贝; 复写; 重复sanitize['sænitaiz]vt. 采取卫生措施使其安全, 消毒, 使无害1.Meet pythonPython is a lot like any other general-purpose programming language, with statements, expressions , operators , functions , modules, methods, and classes .IDEL是Python的编辑环境,TAB键可以给出提示语句Alt-P重复之前的命令,比如上一个命令是print,再向上是1+2命令,则按一次Alt-P会出现print命令,按两次出现1+2命令Alt-N重复下一个命令,其实是循环到第一个命令。
不再是页面地标准.开发人员和决定还是继续拓展和改进新地、更为简单地在较老地浏览器上也得到支持,这些浏览器看到这个是会使用标准模式.文档来自于网络搜索<>标记或指向地样式表链接中不再需要属性.现在地和是默认类型文档来自于网络搜索用于指定字符集地<>标记已经大为简化,只包含字符编码现在是上使用地标准字符集和<>标记做出修改不会影响页面在较老地浏览器上显示地元素(原书显示是“新元素”,个人感觉不对)是地一个超集,这说明,较老地页面在现代浏览器中仍能正常工作文档来自于网络搜索引入了一些元素,可以向页面增加新地语义,与相比,可以提供更多选项来创建页面结构.文档来自于网络搜索中地很多新特性都需要来充分加以利用.通过使用,可以与交互,也就是文档对象模型( )文档来自于网络搜索是页面地浏览器内部表示,通过使用,你可以访问元素、修改元素,还可以向增加新元素.文档来自于网络搜索是一个“应用编程接口”利用,可以控制地所有方面,比如绘图、视频回放等.文档来自于网络搜索是直接上最流行地语言之一,最近几年,实现了显著地改进.可以检测浏览器中是否支持某个新特性,如果不支持还能够妥善地降级(适配)是地样式标准,很多人用“”描述创建应用所用地技术家族时,都包含.文档来自于网络搜索地样子这是一个标准地[] ?文档来自于网络搜索< " " ""> 文档来自于网络搜索<><>< "" "; "> 文档来自于网络搜索<>无标题文档<><><><><>起初我以为就是把上面出现地地方都换成就好,没想到比我想象地要容易[] ?文档来自于网络搜索< ><><>< ""><>无标题文档<><><><><>其中简化了和,地脚本链接也简化了地(这个例子没有显示)可以在网站上验证自己地是那个版本地[] ?文档来自于网络搜索<>< "" "">[] ?文档来自于网络搜索<>< "" "">。
first的用法归纳好嘞,以下是为您创作的关于“first 的用法归纳”:咱来说说“first”这个词,它在咱们的学习中可是相当常见呢!“first”作形容词的时候,表示“第一的;最初的;首要的”。
比如说,“the first day”就是“第一天”,“my first job”就是“我的第一份工作”。
这就好比咱们第一次学骑自行车,那第一天尝试的那种紧张和兴奋,是不是印象特别深刻?我记得我小时候,第一次学骑自行车,那车比我都高。
我爸在后面扶着,我歪歪扭扭地往前蹬,心里直打鼓,就怕摔个大跟头。
可那种想要征服它的劲儿,让我一直坚持。
这“first”就像是那最初的挑战,充满未知和期待。
作副词的时候,“first”表示“首先;第一;最初”。
比如说,“First, let me introduce myself”意思就是“首先,让我来自我介绍一下。
”这就像我们做数学题,得先看清题目,first 搞清楚要求,才能往下做。
“first”还能作名词,意思是“第一;第一个人(或事物)”。
就像比赛中,谁拿到了“first”,那可就是冠军啦!在词组中,“at first”表示“起初;起先”。
比如,“At first, I didn't like the book But later, I found it very interesting”刚开始的时候,我不喜欢那本书。
但后来,我发现它特别有趣。
这就跟吃榴莲似的,一开始闻着那味儿,觉得接受不了。
可鼓起勇气尝了一口之后,哎呀,真香!这“at first”的感觉,是不是常常让我们有意外的反转?“first of all”意思是“首先;第一”,通常用于列举事物。
比如说,“First of all, we need to prepare the materials Then, we can start the project”首先,我们得准备材料。
然后,才能开始这个项目。
headfirst设计模式java_吐血整理HeadFirst设计模式大全首先,要理解Head First设计模式,需要明白设计模式的概念。
设计模式是在软件开发中经过实践验证的解决方案,它们是解决特定问题的经验总结。
Head First系列是一本非常经典的计算机科学图书系列,其中《Head First设计模式》专门介绍了23种常见的设计模式,并以Java语言进行讲解。
本书从实际问题出发,用生动形象的方式讲解设计模式,以帮助读者更好地理解和应用这些设计模式。
下面将介绍一些书中提到的设计模式和其在Java编程中的应用。
1. 策略模式(Strategy Pattern):策略模式将一组行为封装成策略类,使其在运行时可以相互替换。
在Java中,可以使用接口来定义策略,不同的策略类实现相同的接口,根据不同情况选择不同的策略。
2. 观察者模式(Observer Pattern):观察者模式定义了对象间的一种一对多的关系,当一个对象状态改变时,所有依赖它的对象都会被通知并自动更新。
在Java中,可以使用java.util.Observable类和java.util.Observer接口来实现观察者模式。
3. 装饰者模式(Decorator Pattern):装饰者模式动态地将责任附加到对象上,通过创建一个装饰者类来包装原始对象,以提供额外的功能。
在Java中,可以通过继承原始对象并添加额外功能的方式来实现装饰者模式。
4. 工厂模式(Factory Pattern):工厂模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。
在Java中,可以使用工厂方法模式来实现,通过定义一个工厂接口和具体的工厂类来创建实例。
5. 单例模式(Singleton Pattern):单例模式确保一个类只有一个实例,并提供一个全局访问点。
在Java中,可以使用私有构造函数和静态方法来实现单例模式。
以上只是其中一部分介绍的设计模式,还有其他如适配器模式、迭代器模式、模板方法模式等。
《Head First HTML and CSS》读后感精选10篇《Head First HTML and CSS》是一本由Elisabeth Robson / Eric Freeman著作,O'Reilly Media出版的Paperback图书,本书定价:USD 39.99,页数:768,特精心从网络上整理的一些读者的读后感,希望对大家能有帮助。
《Head First HTML and CSS》读后感(一):看起来很厚,读起来很薄Head First 系列的特色就是:* 图片很多* 每章的内容(包括遣词造句)都是按模板来写的* 所以只要你能看懂其中一章,那么其他章节基本上都能看懂(专业术语可能要查一下资料)别看它有七百多页而且还是英文的,只要你去读就会发现其实没那么厚,没那么难懂。
《Head First HTML and CSS》读后感(二):注意你看的版本HTML与CSS有两版,第一版是2022年出的,书名是HTML, CSS和XHTML,中文版是2022年出的,第二版是2022年出的,书名是HTML和CSS,没有中文版不用说应该尽量看新版,新版对HTML5,mobile web等都有涉及,旧版已经将近10年,虽然语法没变,但标准,设备和网络环境已经变了很多,直接看新版更利于快速进入实战阶段《Head First HTML and CSS》读后感(三):敢不要这么啰嗦么?在headfirst的官网没有这本书的源码下载,甚至书籍列表里找不到书名...这本书真的是headfirst系列的?从书的编辑风格来说和其他书一样,但是真尼玛啰嗦。
别的headfirst是为了讲道理搞一些小对话小故事,这货是干凑对话故事啊,全都是废话。
到处都是“这个后面再说”“那个后面再说”其实都是一句话就说清楚的事。
哪怕你后面重复一遍加深印象也好。
img一个标签扯了一整章,这本书如果压缩掉四分之一到三分之一会是一本好书。
《HeadFirst设计模式》阅读笔记.第十三章2010-04-13《Head First设计模式》阅读笔记.第十三章文章分类:Java编程1、与设计模式相处模式:是在某种情境下(Context),针对某个问题的某种解决方案。
连连看解答:引用------------------------------------------装饰者(Decorator)模式:包装一个对象,以提供新的行为。
状态(State)模式:封装了基于状态的行为,并使用委托在行为之间切换。
迭代器(Iterator)模式:在对象的集合之中游走,而不暴露集合的实现。
外观(Facade)模式:简化一群类的接口。
策略(Strategy)模式:封装可以互换的行为,并使用委托来决定使用哪一个。
代理(Proxy)模式:包装对象,以控制对此对象的访问。
工厂方法(Factory Method)模式:允许客户创建对象的家族,而无需指定他们的具体类。
适配器(Adapter)模式:封装对象,并提供不同的接口。
观察者(Observer)模式:让对象能够在状态改变时被通知。
模板方法(Template Method)模式:由子类决定如何实现一个算法中的步骤。
组合(Composite)模式:客户用一致的的方式处理对象集合和单个对象。
单态/单件(Singleton)模式:确保有且只有一个对象被创建。
抽象工厂(Abstract Factory)模式:由子类决定要创建的具体类是哪一个。
命令(Command)模式:封装请求成为对象。
------------------------------------------Sharpen your pencil解答-模式的分类:引用------------------------------------------创建型:工厂方法(Factory Method)、抽象工厂(Abstract Factory)、单态/单件(Singleton)。
《Head.First设计模式》读书笔记目录1、创建型设计模式 (1)1.1工厂方法Factory Method【类】与抽象工厂Abstract Factory【对象、chapter 4】 (1)1.2单件Singleton【chapter5、对象】 (2)2、结构型设计模式 (2)2.1适配器Adapter【chapter7、类/对象】 (2)2.2组合Composite【chapter9、对象】 (2)2.3装饰者Decorator【chapter3、对象】 (2)2.4外观Facade【chapter7、对象】 (3)2.5代理Proxy【chapter11、对象】 (3)3、行为型设计模式 (3)3.1模板方法Template Method【chapter8、类】 (3)3.2命令Command【chapter6、对象】 (3)3.3迭代器Iterator【chapter9、对象】 (4)3.4观察者Observer【chapter2、对象】 (4)3.5状态State【chapter10、对象】 (4)3.6策略Strategy【chapter1、对象】 (4)4、与设计模式相处 (5)1、创建型设计模式1.1工厂方法Factory Method【类】与抽象工厂Abstract Factory【对象、chapter 4】(1) 工厂方法Factory Method:定义:由子类决定要实例化的类是哪一个。
让类把实例化推迟到子类。
实例:拓展披萨工厂,有各地风味的加盟店。
实现:分为Product(产品类披萨)和Creator(创建者类PizzaStore)两个类层级,都有许多具体的子类,每个子类都有自己特定的实现。
相关:“依赖倒置原则Dependency Inversion Principle”【6】。
要依赖抽象,不要依赖具体类。
PizzaStore是高层组件、比萨实现是低层组件,前者依赖后者。
Head First 设计模式介绍Head First 设计模式是一本由埃里克·弗里曼(Eric Freeman)、伊丽沙白·弗里曼(Elisabeth Freeman)、考思温·西迪(Kathy Sierra)和贾尼特·贝茨(Bert Bates)合著的图书,该书使用了一种独特的学习方式,通过大量的图表、示例和练习来帮助读者理解和实践面向对象设计模式。
本文档将对 Head First 设计模式进行简要概述,并介绍其中涵盖的几种常见的设计模式。
设计模式概述设计模式是在软件开发过程中经常出现的问题的解决方案。
它们旨在提供一种通用的方法,帮助开发人员解决特定类型的问题。
设计模式有助于提高软件的可重用性、可维护性和可扩展性。
Head First 设计模式一书介绍了23种常见的设计模式,分为三种类型:创建型模式、结构型模式和行为型模式。
•创建型模式:这些模式关注对象的创建过程,包括如何实例化对象和配置对象的创建流程。
•结构型模式:这些模式关注对象之间的组合,以建立更大的结构,并提供对象之间的简化操作。
•行为型模式:这些模式关注对象之间的交互和通信,以实现特定的行为和协作。
以下是 Head First 设计模式中介绍的一些常见设计模式:创建型模式单例模式单例模式确保一个类只有一个实例,并提供一个全局访问点来访问该实例。
通过单例模式,我们可以限制对某个类的实例化,避免多个对象同时存在。
工厂模式工厂模式是一种创建型模式,它定义了一个创建对象的接口,但将具体的实现交给了子类来决定。
工厂模式可以通过将对象的创建和使用解耦,从而提供一种灵活的方法来创建多个对象的实例。
结构型模式适配器模式适配器模式将一个类的接口转换为客户端所期望的另一个接口,从而使两个类能够协同工作。
适配器模式适用于需要将一个类集成到另一个类中,并且不能修改原有类的情况。
装饰器模式装饰器模式允许在不改变现有对象结构的情况下,动态地添加行为。
Chapter 1 Intro to Design Patterns (4)It started with a simple SimUDuck app (4)But now we need the ducks to FLY (4)But something went horribly wrong... .. (4)Joe thinks about inheritance... .. (4)How about an interface? (4)What would you do if you were Joe? (5)把变化的和不变的分开处理 (5)面向接口编程而非过程 (5)面向接口编程就是面向父类类型编程 (6)HAS-A can be better than IS-A (6)The Strategy Pattern (7)Chapter 2 The Observer Pattern (7)在彼此互动的对象之间力求做到松散耦合 (8)Chapter 3 The Decorator Pattern(装饰者模式) (8)The Open-Closed Principle (9)装饰者模式的定义 (9)装饰者模式的缺点 (10)Chapter 4 the Factory Pattern (10)简单工厂模式 (11)PizzaStore工厂 (11)parallel class hierarchies (12)工厂模式的官方定义 (12)工厂模式的优点 (12)Dependency Inversion Principle (12)A few guidelines to help you follow the Principle... . (13)抽象工厂模式 (13)工厂模式和抽象工厂模式的区别 (13)Chapter 5 the Singleton Pattern (14)它有什么用? (14)可不可以用全局变量来代替单例模式? (14)它有啥优点? (14)一个简单的单例模式 (14)Singleton Pattern defined (15)多线程环境下的单例模式 (15)Chapter 6 the Command Pattern(Encapsulating Invocation) (16)the Command Pattern官方定义 (16)NoCommand (17)undo action (17)MacroCommand (17)队列需求 (18)记录需求 (18)Chapter 7 the Adapter and Facade Patterns(Being Adaptive) (19)到底什么是适配器模式? (19)Adapter Pattern defined (20)Object and class adapters (20)它俩各自的优劣 (20)Real world adapters (21)装饰者模式和适配器模式的区别 (21)The Façade Pattern (21)Facade Pattern defined (22)The Principle of Least Knowledge (22)How NOT to Win Friends and Influence Objects (22)Keeping your method calls in bounds (23)The Facade and the Principle of Least Knowledge (23)The Template Method Pattern——Encapsulating Algorithm (23)Template Method Pattern defined (24)Hooked on Template Method (24)The Hollywood Principle (24)Template Method in the Wild (25)它和策略模式的区别 (25)chapter 9 the Iterator and Composite Patterns——Well-Managed Collections (25)The Iterator Pattern (25)Adding an Iterator to DinerMenu (26)Making some improvements (26)Iterator Pattern defined (27)Single Responsibility (27)Iterators and Collections in Java5 (27)The Composite Pattern (28)如何将The Composite Pattern和Iterator Pattern合二为一? (28)Implementing the Composite Menu (29)如何将iterator融入composite pattern中? (29)The Null Iterator (29)复合模式总结 (30)Chapter 10 The State of Things——the State Pattern (30)如果把这些状态转换为代码 (31)The new design (31)The State Pattern defined (32)the State Pattern与the Strategy Pattern的区别 (32)Chapter 11 the Proxy Pattern——Controlling Object Access (32)The role of the ‘remote proxy’ (33)Java RMI (33)如何实现一个远程服务? (33)Step one: make a Remote interface (33)为啥Java中有个序列化呢? (34)The Proxy Pattern defined (34)代理模式的类图描述 (35)Get ready for Virtual Proxy (35)代理模式的共同点: (35)代理模式与装饰者模式的区别 (35)代理是怎样产生的? (35)Using the Java API’s Proxy to create a protection proxy (36)如何判断一个类是不是代理类? (36)Chapter 12 Compound Patterns——Patterns of Patterns (36)The King of Compound Patterns (37)MVC的模式组合分析? (37)MVC and the Web (37)总结: (38)Chapter 13 Better Living with Patterns——Patterns in the Real World (39)Design Pattern defined (39)Chapter 1 Intro to Design PatternsIt started with a simple SimUDuck app作者以一个鸭子游戏为例展开叙述,很普通,它也选择设计一个抽象父类Duck,该父类具有鸭子普遍具有的特征,其下有若干个鸭子子类。
HeadFirst 学习笔记1. 书中列举的设计原则1、封装变化。
找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起。
2、针对接口编程,而不是针对实现编程。
举例说明:假设有一个抽象类Animal,有两个具体的实现(Dog与Cat)继承Animal。
“针对实现编程”的做法:Dog d = new Dog();d.bark();“针对接口编程”的做法:Animal animal = new Dog();animal.makeSound();或者:Animal animal = getAnimal();animal.makeSound();3、多用组合,少用继承。
原因:a、继承会使类无限膨大,可能会使类变得臃肿。
b、子类可能会继承父类中那些无用甚至有害的方法。
c、组合比继承更灵活,可以实现在执行中动态改变对象的功能。
4、为了交互对象之间的松耦合设计而努力。
5、类应该对修改关闭,对扩展开放。
6、要依赖抽象,不要依赖具体类。
解释:不要让“高层组件”依赖“低层组件”,而且,不管“高层组件”还是“低层组件”,两者都应该依赖于抽象。
避免违反该原则的几个方针:1)变量不可以持有具体类的引用。
如果使用new,就会持有具体类的引用,可以使用工厂来避开这种引用。
2)不要让类派生自具体类。
如果派生自具体类,就会依赖具体类,可以派生自抽象或接口。
3)不要覆盖基类中已实现的方法。
如果覆盖基类中已实现的方法,那么基类就不是一个真正适合被继承的类。
基类中已实现的方法应该被所有子类所共享。
7、最少知识原则。
解释:当你设计一个系统时,不管是任何对象,你都要注意与它交互的类有哪些,并注意它和这些类是如何交互的,尽量避免过多的类耦合在一起,带来维护成本的上升。
这个原则推荐的一些方针:就任何对象而言,在该对象的方法内,我们只应该调用一下范围的方法1)、该对象本身2)、被当作方法的参数而传递进来的对象3)、此方法所创建或实例化的任何对象4)、对象的任何组件。
2. 策略模式先对策略模式有一个总体认识。
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
本模式使得算法可独立于使用它的客户而变化。
结构:下面通过鸭子模拟器的设计来具体介绍。
公司需要设计一套鸭子模拟器系统,该系统的第一次需求为:鸭子能够戏水;鸭子能够呱呱叫。
根据该需求系统设计如下:这个设计主要用了父类鸭子和子类绿头鸭、红头鸭,这样设计的目的是为了达到代码的复用。
过了一段时间,公司希望该系统能够满足新的需求:有些鸭子会飞。
因此该系统需要进行修改,修改后的系统可能如下:该系统在父类中加了“fly()”方法(在父类中加该方法是为了实现代码的复用)。
这里就出现了两个问题:(1)、所有的鸭子都会飞了。
(2)、所有鸭子的叫声都一样,都是“呱呱”叫。
注:这两个问题可以通过子类中方法覆盖来解除,但这样处理不是很好。
鸭子的类别越多,这种处理的缺点就越明显。
其实这个系统的变化点是鸭子的叫声和鸭子的飞行能力,因此我们很容易想到把鸭子的叫声和鸭子的飞行能力做成接口,把这些变化的地方封装起来,这样上面的两个问题都可以解决,所以系统可能被修改为下面的样子:MallardDuck和RedheadDuck既会飞又会叫,RubberDuck只会叫不会飞,DecoyDuck不会飞也不会叫。
应该说这个系统没有问题了,从表面看这种设计完全符合需求,而且完全符合面向对象的理念,但是当鸭子的类别很多时,你会发现这种设计缺乏代码的复用,这两个独立出来的接口似乎没有任何意义,根本无法减轻工作量,还不如原来的设计呢。
所以你可能会想到问题的关键是接口中的方法没有实现,那我们该怎么办呢?我们的做法是把接口做成类,运用组合的方法来实现需求。
考虑到“针对接口编程,而不是针对实现编程”的设计原则,我们的系统可能就会设计成如下的结构,这个结构就是应用了“策略”模式。
3. 观察者模式意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
结构:例子:下面以模拟气象站系统来加以说明。
需求分析:该系统的需求如下:1、气象站能够追踪目前的天气状况,包括温度、湿度、气压、2、气象站能够提供三种布告板,分别显示目前天气状况、气象统计和简单的预报。
3、布告板上的数据必须实时更新。
4、气象站必须提供一组API,供其他开发人员开发其他的布告板。
设计部分:基于以上需求,该系统可以设计成3部分:气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)和布告板(显示目前的天气状况给用户看)。
效果图如下:错误的类图设计(即没有学过设计模式时的第一感觉)可能如下:相应的代码实现部分:1public void MeasurementsChanged()2 {3 temperature = this.GetTemperature(); // 获得温度4 humidity = this.GetHumidity(); // 获得湿度5 pressure = this.GetPressure(); // 获得气压67 MyCurrentConditionsDisplay.Update(temperature, humidity, pressure); // 更新目前天气状态板8 MyStatisticsDisplay.Update(temperature, humidity, pressure); // 更新气象统计板9 MyForcastDisplay.Update(temperature, humidity, pressure); // 更新天气预报板10 }这个类图设计的缺点:1)、该设计是针对具体实现编程,而非针对接口。
2)、对于每个新的布告板,我们都得修改代码。
3)、我们无法在运动时动态得增加或删除布告板。
4)、我们尚未封装改变的部分。
那么如何改正这些缺点呢?首先我们必须明白这些缺点的根源在哪里。
很明显,我们在类图设计时依赖关系错了,应该依赖倒置。
CurrrentConditionsDisplay类、StatisticsDisplay类和ForcastDisplay类应该依赖WeatherData 类,而不是相反,这样就可以起到解耦的目的。
其次,CurrrentConditionsDisplay类、StatisticsDisplay类和ForcastDisplay类都有一个Update ()方法,因此应该提炼一个接口,这样可以实现“针对接口编程”,使代码更加灵活,也方便其他开发人员开发其他的布告板。
进一步思考:1)、改正这些缺点后,我们的类图已经与观察者模式的结构有点类似了。
2)、我们的气象站系统的最大问题其实就是一对多的依赖引起的,而观察者模式正是解除一对多关系的不二法门,因此我们有必要采用观察者模式。
采用了观察者模式后设计的类图应该是这样:WeatherDatea实现ISubject接口,CurrentConditionsDisplay、ForcastDisplay、StatisticsDisplay 实现IObserver接口,ISubject调用IObserver,CurrentConditionsDisplay、ForcastDisplay、StatisticsDisplay调用ISubject。
4. 装饰者模式意图:动态地将责任附加到对象上。
若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
结构:例子:下面我们以星巴兹(Starbuzz)的订单系统为例加以说明。
需求分析:1)、星巴兹的饮料(Beverage)种类繁多,主要有HouseBlend、DarkRoast、Decaf、Espresso。
2)、星巴兹的调料很多,主要有Steamed Milk、Soy、Mocha、Whip。
3)、星巴兹的饮料价格是根据饮料的基础价和所加入的调料的价格相加得到。
错误设计:根据以上的简单分析,第一种类图设计出炉:其中getDescription()用来描述饮料,cost()用来计算价格。
显而易见,这个类图设计的最大缺点就是类太多,系统难以维护。
所以我们需要另外的解决方案,而且新方案必须避免“类爆炸”。
此时我们想到了实例变量和继承。
先从Beverage基类下手,加上实例变量代表是否加上调料(Steamed Milk、Soy、Mocha、Whip等),Beverage基类的cost()计算调料的价钱,而各种具体的饮料(HouseBlend、DarkRoast、Decaf、Espresso等)的cost()将把基础饮料的价钱和调料的价钱相加得到饮料的价钱。
由此可以设计出第二种类图。
对这个类图设计的评价:如果需求不再变化,那么这个类图设计没有错;但是需求发生了变化,这个设计就会难以招架。
经过进一步的分析,我们发现部分需求被我们遗漏了。
新增加的需求:1)、调料的价格可能发生变化。
2)、调料的种类可能发生变化。
3)、饮料的种类可能增加,不只HouseBlend、DarkRoast、Decaf、Espresso四种。
4)、顾客可能在一种饮料里加双份的同种饮料。
显然,第二种类图设计难以满足新的需求,而且对新增加的饮料而言,有可能存在不适合的调料。
例如,茶子类将继承hasWhip()(加奶泡)等方法。
因此,我们应该对类图设计进行改进。
此时我们想到了装饰者模式,那么如何应用装饰者模式呢?以装饰者模式构造饮料订单:1)、以DarkRoast对象开始。
2)、顾客想要Mocha,所以建立一个Mocha对象,并用它将DarkRoast对象包装起来。
3)、顾客也想要Whip,所以需要建立一个Whip装饰者,并用它将Mocha对象包起来。
4)、现在,该是为顾客算钱的时候了。
通过最外圈装饰者(Whip)的cost()就可以办得到。
Whip的cost()会先委托它装饰的对象(Mocha)计算出价钱,然后再加上Whip的价钱。
根据以上的分析,应用装饰者模式,我们可以打造一个全新的类图。
第三种类图设计(正确的类图):部分代码为:1public class DarkRoast : Beverage2 {3public DarkRoast()4 {5 description = "Dark Roast";6 }7public override double Cost()8 {9return1.22;10 }11 }12public class Mocha : CondimentDecorator13 {14 Beverage myBeverage;15public Mocha(Beverage paramBeverage)16 {17this.myBeverage = paramBeverage;18 }1920public override string GetDescription()21 {22return myBeverage.GetDescription() + ",Mocha";23 }2425public override double Cost()26 {27return0.5 + myBeverage.Cost();28 }29 }30class StarbuzzCoffee31 {32static void Main(string[] args)33 {34 Beverage myBeverage = new Espresso();35 Console.WriteLine(myBeverage.GetDescription() + " $" + myBeverage.Cost());3637 Beverage myBeverage2 = new DarkRoast();38 myBeverage2 = new Mocha(myBeverage2);39 myBeverage2 = new Mocha(myBeverage2);40 myBeverage2 = new Whip(myBeverage2);41 Console.WriteLine(myBeverage2.GetDescription() + " $" + myBevera ge2.Cost());4243 Console.ReadLine();44 }45 }装饰模式的适用情况:1)、需要扩展一个类的功能,或给一个类增加附加责任。