查看: 1406|回复: 0

[.NET源码] 小菜读书--《大话设计模式》

发表于 2018-3-23 08:00:05

虽然有过三年的开发经历,但是还是小菜一枚,在大鸟的指导下,开始专业化进入软件这条道路。

首先大鸟推荐第一本书籍,就是《大话设计模式》。一边做笔记一边看书,书中以身边的故事,引出6种设计原则&23种设计模式。

历练使人成长,经验迸发灵感。然而所有的灵感都应有其因,那就是万变不离其宗的六大面向对象的设计原则,即单一职责原则、开放--封闭原则、依赖倒转原则、里氏代换原则、迪米特法则和合成--聚合复用原则。但这六大原则仅仅是一系列的“口号”,真正付诸实施还需要有详尽的指导方法,于是23种设计模式应运而生。归根到底,就是通过重构改善既有代码,使代码的耦合度降低,最终实现易维护、易扩展、易复用和灵活性好的编程设计,得到精彩的代码。

写这篇文章的主要目的,是为了记录我此时的学习状态和心得,以便日后回顾。同时也为正在软件行业彷徨的小伙伴们指点路途。

一.六种设计原则(核心:强内聚,松耦合)

1.单一职责原则

Story:手机功能齐全,但一在关键时刻就“萎”掉;

Concept:就一类而言,应该只有一个引起它变化的原因,体现了类的职责分离。

Tips:如mvc架构,实现逻辑和界面的分离。

2.开放--封闭原则

Story:考研&找工作两手抓,香港澳门一国两制;

Concept:是所有面向对象原则的核心。软件实体应该是可扩展,而不可修改的。即对扩展是开放的,而对修改是封闭的。

Tips:应该仅对程序中呈现出频繁变化的那些部分做出抽象,拒绝不成熟的抽象和抽象本身一样重要。

3.依赖倒转原则

Story:修电脑门槛低,因为PC电脑的主板、CPU和内存等针对接口设计,而不是针对实现设计,耦合程度低,依赖性弱,易维修;而收音机过多强耦合开发,难排查,难维修;

Concept:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象;

Tips:(1)应针对接口编程,不要对实现编程;因为针对实现来设计内存,就要对应到具体的某个品牌的主板,那会出现换内存需要把主板也换了的尴尬;

(2)依赖倒转原则其实是面向对象设计的标志。若编写时考虑的都是针对抽象编程即为面向对象设计;反之,针对细节编程即为过程化的设计;

4.里氏代换原则

Story:继承关系,如鸟类&企鹅类;

Concept:在软件中,把父类都替换成它的子类,而程序的行为没有变化。子类型必须能够替换他们的父类型;正是由于子类型的可替换性才使得使用父类型的模块在无需修改的情况下就可以扩展;

Tips:里氏代换原则是对开放--封闭原则的补充。实现开放--封闭原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

5.迪米特法则

Story:无熟人难办事,主要是处理权限问题;

Concept:也叫最少知识原则。类之间的耦合越弱,就越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。 主要是强调了类之间的松耦合;

Tips:在类的设计上,每一个类都应当尽量降低成员的访问权限。

6.合成--聚合复用原则

Story:硬件厂商生产的硬件与软件厂商生产的软件为合成关系;手机品牌包含的手机软件为聚合关系;

Concept:合成聚合是“has a”的关系,而继承是“is a”的关系。由于继承是一中强耦合的结构,父类变,子类必变。所以不是“is a”关系,我们一般不要用继承。优先使用合成聚合复用原则,有助于保持每个类的封装,降低继承的层次。

Tips:尽量使用合成/聚合,尽量不使用类继承。

二. 23种设计模式

A.创建型模式

1.简单工厂模式

Story:计算器的功能设计与实现;

Concept:又叫做静态工厂方法模式,是由一个工厂对象决定创建出哪一种产品类的实例;

Tips:提供一个创建一系列或相关依赖对象的接口,而无需指定它们具体的类。

2.建造者模式

Story:炒面没放盐,千家千味,而肯德基麦当劳千家一味;建造小人物;

Concept:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。用户只需要指定建造的类型,而无需知道具体建造的过程与细节。

Tips:Builder接口的对象是用于创建一些复杂的对象,这些对象内部构建间的建构顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。其好处就是,使建造代码与表示代码分离。

3.工厂方法模式

Story:学雷锋,不留名,志愿者爱心行动相传。

Concept:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

4.原型模式

Concept:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象;

Tips:主要用于对象的复制,它的核心是就是类图中的原型类Prototype。使用原型模式的一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。

5.单例模式

Concept:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

Tips:单例模式可让类自身负责保存它的唯一实例。

B.结构型模式

6.适配器模式

Story:姚明在NBA需要翻译;

Concept:将一个类的接口适配成用户所期待的。包括类适配器模式和对象适配器模式;

Tips:主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。只有在无法改变原有设计和代码的情况下才考虑适配;

7.桥接模式

Story:手机品牌不统一,软件不兼容;

Concept:将抽象部分与它的实现部分分离,使他们都可以独立地变化。

8.组合模式

Story:为有分销机构的大公司做办公管理系统;

Concept:将对象组合成树形结构以表示“部分——整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性;

Tips:使用条件为:当需求中体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时;

9.装饰模式

Story:穿何种服装见女朋友;

Concept:每个装饰对象的实现和如何使用这个对象分离开;

Tips:这样做的最大好处就是有效地把类的核心职责和装饰功能区分开,而且可以去除相关类中重复的装饰逻辑。

10.外观模式

Story:股票投资风险大,众多投资者与众多股票联系太多,反而不利于操作;而基金是基金经理人与上千股票和其他投资产品打交道,风险更小;

Concept:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用;

Tips:使用情况:(1)在设计初期阶段,应该要有意识地将不同的两个层分离;(2)在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂。若增加Fa?ade可以提供一个简单的接口,以减少它们之间的依赖性;(3)在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展,这时,可以为新系统开发一个Fa?ade类,来提供设计粗糙或高度复杂和遗留代码比较清晰的接口,让新系统与Fa?ade对象交互,Fa?ade与遗留代码交互所有复杂的工作;

11.亨元模式

Concept:以共享的方式高效地支持大量的细粒度对象;

Tips:1)享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化;

12.代理模式

Story:卓贾易通过戴励送娇娇东西,结果戴励与娇娇恋爱了;

Concept:在访问对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。

Tips:代理模式包括:远程代理、虚拟代理、安全代理和智能指引;

C.行为型模式

13. 观察者模式

Story:上班炒股,前台秘书通风报信;要求前台类与观察者双向耦合;

Concept:定义一种一对多的关系,让多个观察者对象同时监听某一主题对象;

Tips:当不知道具体有多少对象有待改变时,应该考虑使用观察者模式。实则在解耦合,让耦合双方都依赖于抽象,而不是依赖于具体;

14.模板方法模式

Story:看不懂英文试题,会做也白搭;

Concept::在一个方法中定义一个算法的骨架,而将一些实现步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤;

15.命令模式

Story:打游击烤羊肉串的档口对请求排队或记录请求日志以及支持可撤销操作,其实是“行为请求者”与“行为实现者”的紧耦合;做烤肉的开门店反之;

Concept:将一个请求封装一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志以及支持可撤销操作;

Tips:敏捷开发原则;

16.状态模式

Story:不同时间人的精神状态不同;

Concept:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

Tips:状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。其好处是,将与特定状态相关的行为局部化,并且将不同状态的行为分割开来;

17.职责链模式

Story:设计加薪代码;

Concept:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。

18.解释器模式

Story:明白老板的评价背后潜台词;

Concept:如果一个特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子;

Tips:可构建一个解释器通过解释这些句子来解决该问题;

19.中介者模式

Story:安理会&联合国等调停组织;

Concept:又叫调停者模式,定义一个中介对象来封装系列对象之间的交互。中介者使各个对象不需要显示地相互引用,从而使其耦合性松散,而且可以独立地改变他们之间的交互。

20.访问者模式

Story:man & woman的异同;

Concept:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

Tips:目的是把处理从数据结构中分离出来;

21.策略模式

Story:商场促销中各种折扣优惠的实现;

Concept:定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换,让算法独立于使用它的客户而独立变化;

Tips:优点是:简化了单元测试;

22.备忘录模式

Story:游戏存储进度;

Concept:在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

Tips:涉及角色:发起人(Originator)、备忘录(Memento)和管理者(Caretaker);

23.迭代器模式

Story:售票员进行迭代遍历检票,不放过漏网之鱼;

Concept:提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示;

Tips:分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让多部代码透明地访问集合内部的数据;



回复

使用道具 举报