阅读《HeadFist设计模式》笔记

前段时间看了《Head First 设计模式》这本是,感觉挺不错,通俗易懂,不过理论归理论,要真正把那些设计模式恰到好处应用到现实的开发中,还是需要不断实践和积累经验的。以下是自己看这本过程中从书本中摘录的一些概念、原则之类的(主要讲到十二种设计模式,九条设计原则)。当做是自己的学习记录。


Chapter1:


1.使用模式最好的方式是:“把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们。”以往是代码重复,现在是经验复用。

2.软件开发的一个不变的真理:change(不变的是变化)
不管当初软件的设计得多好,一段时间之后,总是需要成长与改变的,否则软件就会死亡。

3.第一个设计原则:
找出应用中可能需要变化之处,把它们从应用中独立出来,不要和那些不需要变化的代码混在一起。(即:把会变化的部分取出并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的其他部分。)
结果:代码变化引起的不经意后果变少,系统变得更有弹性。

4.第二个设计原则:
针对接口编程,而不是针对实现编程。

5.“针对接口编程”真正的意思是“针对超类型(supertype)编程”。

6.第三个设计原则:
多用组合,少用继承。

*********************************
7.第一个设计模式:
策略模式:定义了算法族,分别分装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
*********************************

8.共享模式词汇的威力
你使用模式和其他人沟通时,其实“不只是”和他人共享“行话”而已。
共享的模式词汇“威力强大”。
模式能够让你用更少的词汇做更充分的沟通。
将说话的方式保持在模式层次,可让你待在“设计圈子”久一点。
共享词汇可帮你的开发团队快速充电。
共享词汇能帮助初级开发人员迅速成长。

9.知道抽象、分装、继承、多态这些概念,并不会马上让你变成好的面向对象设计这。设计大师关心的是建立弹性的设计,可以维护,可以应付变化。

10.建立可维护的OO系统,要诀就在于随时想到系统以后可能需要的变化以及应付变化的原则。

---------------------------------
Chapter2:

*********************************
11.第二个设计模式:
观察者模式:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
*********************************

12.松耦合的威力
当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。
观察者模式提供了一种对象设计,让主题和观察者之间松耦合。

13.第四个设计原则:
为了交互对象之间的松耦合设计而努力。

14.松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,因为对象之间的相互依赖降到了最低。

---------------------------------
Chapter3:

15.运行时扩展,远远比编译时期的继承威力大。

16.牢记代码应该如同晚霞中的莲花一样关闭(免于改变),如同晨曦中的莲花一样地开放(能够扩展)。

17.第五个设计原则:
类应该对扩展开发,对修改关闭。(开放-关闭原则)

18.我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。如能实现这一的目标,有什么好处?这样的设计具有弹性,可以应对改变,可以接受新的功能来应对改变你的需求。

*********************************
19.第三个设计模式:
装饰者模式:动态地将对象附加到对象上。若要扩张功能,装饰者提供了比继承更有弹性的替代方案。
*********************************
----------------------------------
Chapter4:

*********************************
20.第四个设计模式:
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
*********************************

21.工厂方法和创建者不总是抽象的,可以定义一个默认的工厂方法来产生某些具体的产品,这么一来,即使创建者没有任何子类,依然可以创建产品。


22.“依赖倒置原则(Dependency Inversion Principle)”--这个专有名词可以令周围的人对你刮目相看。你所获得的加薪,将比买本书所付出的钱更多,而且还会赢得其他开发人员的钦佩。

23.第六个设计原则:
要依赖抽象,不要依赖具体类。(代码里减少对具体类的依赖,正式名为“依赖倒置原则”,该原则和第二个设计原则“针对接口编程,不针对实现编程”很相似,但这里更强调“抽象”。这个原则说明了:不能让高层组件依赖底层组件,而且,不管高层或底层组件,“两者”都应该依赖于抽象。)

24.想要遵循依赖倒置原则,工厂方法并非是唯一的技巧,但却是最有威力的技巧之一。

25.在依赖倒置原则中的倒置指的是和一般OO设计的思考方式完全相反。

26.下面的指导方针,能帮你避免在OO设计中违反依赖倒置原则:
1)变量不可以持有具体类的引用。(如果使用new,就会持有具体类的引用。你可以改用工厂来避开这一的做法。)
2)不要让类派生自具体类。(如果派生子具体类,你就会依赖具体类。请派生自一个抽象(接口或抽象类))
3)不要覆盖基类中已实现的方法。(如果覆盖基类已实现的方法,那么你的基类就不是一个真正适合被继承的抽象。基类中已实现的方法,应该由所有的子类共享。)

*********************************
27.第四个设计模式:
抽象工厂模式:提供了一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
*********************************

28.工厂方法模式和抽象工厂模式:
1)工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象。
2)抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。

----------------------------------
Chapter5:

*********************************
29.第五个设计模式:
单件模式:确保一个类只有一个实例,并提供一个全局访问点。
*********************************

30.在java中实现单件模式需要私有的构造器、一个静态方法和一个静态变量。

31.单件模式处理多线程的方式:

1)使用getInstance()创建实例
public class Singleton{
private static Singleton uniqueInstance;
private Singleton(){}
public static synchronized Singleton getInstance(){//使用关键字 synchronized控制同步
if(uniqueInstance == null){
uniqueInstance == new Singleton();
}
return uniqueInstance;
}
}

2)使用“急切(eagerly)”创建实例

public class Singleton{
private static Singleton uniqueInstance = new Singleton();//在静态初始化器重创建单件。这段代码保证了线程安全
private Singleton(){}
public static Singleton getInstance(){
return uniqueInstance; //已经有了实例,直接使用
}
}

3)使用“双重检查加锁(double-checked locking)”,在getInstance()中减少使用同步
public class Singleton{
private volatile static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if(uniqueInstance == null){
uniqueInstance == new Singleton();
}
return uniqueInstance;
}
}

----------------------------------
Chapter6:

*********************************
32.第六个设计模式:
命令模式:将“请求”分装成对象,以便使用不同的请求、队列或日志来参数化其他对象。命令模式也支持可撤销的操作。
*********************************

33.命令可以将运算块打包(一个接收者和一组动作),然后将它传来传去,就像是一般的对象一样。

34.命令模式将发出请求的对象和执行请求的对象解耦。

35.在被解耦的两者之间是通过命令对象进行沟通的。命令对象分装了接受者一个或一组动作。

36.调用者通过调用命令对象的execute()发出请求,这会使得接收者的动作被调用。

37.调用者可以接收命令当作参数,甚至在运行时动态进行。

38.命令可以支持撤销,做法是实现一个undo()方法来回到execute()被执行之前的状态。

39.宏命令是命令的一种简单延伸,允许调用多个命令。宏方法也可以支持撤销。

40.在实际操作时,很常见使用“聪明”对象,也就是直接实现了请求,而不是将工作委托给接收者。

41.命令也可以用来实现日志和事务。

----------------------------------
Chapter7:

*********************************
42.第七个设计模式:
适配器模式:将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
*********************************

43.适配器种类:
类适配器:使用多重继承方式(java不支持)
对象适配器:使用组合方式,更加有弹性。

*********************************
44.第八个设计模式:
外观模式:提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
*********************************

45.三种相似模式的目的:
1).装饰者模式:不改变接口,但加入责任
2).适配器模式:将一个接口转换成另一个接口
3).外观模式:让接口更加简单

46.外观不只是简化了接口,也将客户从组件的子系统中解耦。

47.外观和适配器可以包装许多类,但是外观的意图是简化接口,而适配器的意图是将接口转换成不同的接口。

48.第七个设计原则:
最少知识原则:只和你的密友谈话。(即,当你设计一个系统,不管是任何对象,你都要注意它所交互的类有哪些,并注意它和这些类是如何交互的。)

49.最少知识原则提供了一些方针(对任何对象而言,在该对象的方法内,我们只应该调用属于一下范围的方法):
1).该对象本身
2).被当作方法的参数而传递进来的对象
3).此方法所创建或实例化的任何对象
4).对象的任何组件
exg:

public class Car{
Engine engine; //这是类的一个组件,我们能调用它的方法

public Car(){}


public void start(Key key){
Doors doors = new Doors(); //创建一个新的对象,它的方法可以被调用
bool authorized = key.turns();//被当作参数传递进来的对象,其方法可以被调用

if(authorized){
engine.start(); //可以调用对象组件的方法
updateDashboardDisplay();//可以调用同一对象的本地方法
doors.lock();//可以调用你所创建或实例化的对象的方法
}
}

public void updateDashboardDisplay(){}//本地方法
}

----------------------------------
Chapter8:

50.模板方法定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现。

*********************************
51.第九个设计模式:
模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
*********************************

52.第八个设计原则:
好莱坞原则:别调用我们,我们会调用你。
(好莱坞原则可以给我们一种防止“依赖腐败”的方法。当高层组件依赖低层组件,而低层组件又依赖高层组件,而高层组件又依赖边侧组件,而边侧组件又依赖低层组件时,依赖腐败就发生了。在这种情况下,没有人能够轻易的搞懂系统是如何设计的。)

53.模板方法的抽象类可以定义具体方法、抽象方法和钩子。

54.钩子是一种方法,它在抽象类中不做事,或者只做默认的事情,子类可以选择要不要去覆盖它。

55.为了防止子类改变模板方法中算法,可以将模板方法声明为final。

56.好莱坞原则告诉我们,将决策权放在高层模块中,以便决定如何及何时调用低层模块。

57.策略模式和模板方法模式都分装算法,一个用组合,一个用继承。

58.工厂方法是模板方法的一种特殊版本。

----------------------------------
Chapter9:

*********************************
59.第十个设计模式:
迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
*********************************

60.迭代器模式把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。

61.第九个设计原则:
单一责任:一个类应该只有一个引起变化的原因。(即,尽量让每个类保持单一责任)

62.内聚(cohesion)是一个比单一责任原则更普遍的概念,但两者其实关系是很密切的。遵守这个原则的类容易具有很高的凝聚力,而且比背负许多责任的低内聚类更加容易维护。

63.内聚(cohesion)是用来度量一个类或模块紧密地达到单一目的或责任。

*********************************
64.第十个设计模式:
组合模式:允许你将对象组合成树形结构来表示“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
*********************************

65.组合模式让我们能用树形的方式创建对象的结构,树里面包含了组合以及个别的对象。

66.使用组合结构,我们能把相同的操作应用在组合和个别对象上。换句话说,在大多数情况下,我们可以忽略对象组合和个别对象之间的差别。

67.组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点。

68.在实现组合模式时,有许多设计上的折衷。你要根据需要平衡透明性和安全性。

69.透明性(trransparency):通过让组件的接口同时包含一些管理子节点和叶节点的操作,客户就可以将组合和叶节点一视同仁。也就是说,一个元素究竟是组合还是叶节点,对客户是透明的。

----------------------------------
Chapter10:

*********************************
70.第十一个设计模式:
状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像是修改了它的类。
*********************************

71.状态模式允许一个对象基于内部状态而拥有不同的行为。

72.和程序状态机(PSM)不同,状态模式用类代表状态。

73.通过将每一个状态分装进一个类,我们以后需要做的任务改变局部化了。

74.状态转换可以由State类或Context类控制。

----------------------------------
Chapter11:

75.RMI(Remote Method Invocation)一种用于实现远程过程调用的应用程序编程接口。RMI将客户辅助对象成为stub(桩),服务辅助对象成为(骨架)。

76.制作远程服务五个步骤:
1).制作远程接口(定义了可以让客户远程调用的方法。客户将用它作为服务的类类型。Stub和实际的服务都实现此接口。)
2).制作远程实现(这是做实际工作的类,为远程接口中定义的远程方法提供了真是的实现。这就是客户真正想要调用方法的对象。)
3).利用rmic产生的stub和skeleton(这就是客户和服务辅助类)
4).启动RMI registry(rmiregistry就像是电话本,客户可以从中查到代理的位置)
5).开始远程服务

*********************************
77.第十二个设计模式:
代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
*********************************

78.使用代理模式创建代表(representative)对象,让代表对象控制某对象的访问,被代理的对象可以是远程的对象、创建开销大的对象或需要安全控制的对象。

79.虚拟代理作为创建开销大的对象的代表。虚拟代理经常知道我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,由虚拟代理来扮演对象的替身。对象创建后,代理就会将请求直接委托给对象。

80.Java在java.lang.reflect包中有自己的代理支持,利用这个包你可以在运行时动态的创建一个代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类。因为时机的代理类是在运行时创建的,我们称这个JAVA技术为:代理技术。

81.判断一个类是不是代理类:
代理类有一个静态方法isProxyClass(),此方法返回值如果是true,表示这是一个动态代理类。

82.动态代理类之所以称为动态,是因为运行时才将它的类穿件出来。代码开始执行时,还是没有proxy类,它是根据需要从你传入的接口集创建的。

83.常见代理类别:
1).远程代理
2).虚拟代理
3).保护代理
4).防火墙代理(Firewall Proxy):控制网络资源的访问,保护主题免于“坏客户”的侵害。(用于公司的防火墙系统)
5).智能引用代理(Smart Reference Proxy):当主题被引用时,进行额外的动作,例如计算一个对象被引用的次数。
6).缓存代理(Caching Proxy):为开销大的运算结果提供暂时的存储:它也允许多个客户共享结果,以减少计算或网络延迟。(用于Web服务器代理,以及内容管理与出版系统)
7).同步代理(Synchronization Proxy):在多线程的情况下为主题提供安全的访问。(用于JavaSpaces,为分散式环境内的潜在对象集合提供同步访问控制)
8).复杂隐藏代理(Complexity Hiding Proxy):用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也称为外观代理(Facade Proxy),这不难理解。复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式只提供另一组接口。
9).写入时复制代理(Copy-On-Write Proxy):用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止。这是虚拟代理的变体。

----------------------------------
Chapter12:

84.模式通常被一起使用,并被组合在同一个设计解决方案中。

85.复合模式在一个解决方案中结合两个或多个模式,以解决一般或重复发生的问题。

86.MVC是复合模式,结合了观察者模式、策略模式和组合模式。

87.模型使用观察者模式,以便观察者更新,同时保持两者之间解耦。

88.控制器是视图的策略,视图可以使用不同的控制其实现,得到不同的行为。

89.视图使用组合模式实现用户界面,用户界面通常组合了嵌套的组件,像面板、框架和按钮。

90.这些模式携手合作,把MVC模式的三层解耦,这样可以保持设计干净又有弹性。

91.Model 2是MVC在Web上的应用。

92.在Model 2中,控制器实现成servlet,而JSP/HTML实现视图。

----------------------------------
Chapter13:

++++++++++++++++++++++++++++++++++
93.模式:是在某情境(context)下,针对某问题的某种解决 方案。

++++++++++++++++++++++++++++++++++

94.模式是被“发现的”,而不是被创建的。


你可能感兴趣的:(设计模式,设计原则)