Head First设计模式读书笔记
设计原则:
1.找出应用中可能需要变化的地方,把它们独立出来,不要和那些不需要变化的代码混淆在一起。
ps:这是可扩展性的前提,当需要变化的代码和不需要变化的代码混淆在一起的时候你就无法动态的修改需要变换的地方。
2.针对接口编程,而不是针对实现编程。
ps:这是为了系统有更好的弹性。当针对实现编程的时候,你的这部分代码和实现会耦合在一起从而降低你的代码复用性(只能给这个具体实现用);而针对接口编程后,你的这部分代码可以被任何实现这个接口的实现使用,这个实现可以现在就存在,也可能以后才出现,这使得你的代码变得非常动态。
3.多用组合,少用继承。
ps:这个原则也是为动态变化服务。你想复用某段,我们给这部分代码取名为A,若是采用继承,那么A代码实际上已经被硬编码到你的程序中,哪天你希望不再复用A而是改为复用B代码,OK你可能说你会把父类改为B,要是我希望在同一个程序中有时候复用A有时候复用B呢?傻逼了吧。。若是改为采用组合,那么情况会好很多,你可以将你希望复用的那部分代码动态得设置到你的代码中,无论在什么时候改变都不是问题。
4.为交互对象之间的松耦合设计而努力。
ps:这个原则没什么好吐槽的,松耦合的结构在程序修改的时候更加方便。
5.类应该对扩展开放,对修改关闭。
ps:对扩展开放的好处是可以根据需求为类增加各种不同的新功能,使系统更有弹性,但具体通过什么方式扩展,你可以使用继承的方式,或者使用其他各种组合的方式。对修改关闭是因为修改代码会直接影响到使用这部分代码的用户,产生不可预期的错误。扩展和修改的区别在于扩展实际上是对老代码的复用并新增了一些行为或者特性,这些新行为和特性是可控的,只有在你需要他表现出来的时候才表现出来,而修改是直接修改已有代码,他造成的影响是全局的,所有使用这个代码的地方都会造成影响。
6.要依赖抽象,不要依赖具体类。
ps:这句听起来很像上面的第2条。实际上表述的内容也差不多,这里强调某个类不要依赖于某个容易改变的具体类,而应该依赖于一个不易改变的抽象类。作为一个高层组件,他会使用到一些底层组件,但是高层组件不应该直接在内部new一个具体底层组件类或者使用具体底层组件类型,这样就是高层组件依赖了具体的底层组件,如果底层组件需要改变或者需要被替换掉,那么所有依赖它的高层组件都需要被修改。
7.最少知识原则。
ps:这个原则告诉我们不要让太多的类耦合在一起,这一方面是为了易用性,一方面是为了系统的细节部分修改不会影响到普通的用户。想想TweenLite,想想JQuery,这些以易用性著称的类库往往只暴露一个类供用户使用,并且他们的升级并没有影响到我们使用他们构建出来的程序。
8.好莱坞原则,别调用我们,我们会调用你。
ps:这个原则其实是提醒我们别让系统中的依赖过多,若两个类之间相互依赖,那么任何一方的修改都会影响到另外一方,若是更多的类之间产生纷繁复杂的依赖,那么系统的维护成本将会很高。所以较好的做法是,底层组件不依赖高层组件,底层组件只提供相应的功能供高层组件使用。
9.单一责任原则,一个类应该只有一个引起变化的原因。
ps:一个类,只有一个引起它变化的原因。应该只有一个职责。每一个职责都是变化的一个轴线,如果一个类有一个以上的职责,这些职责就耦合在了一起。这会导致脆 弱的设计。当一个职责发生变化时,可能会影响其它的职责。另外,多个职责耦合在一起,会影响复用性。例如:要实现逻辑和界面的分离。SRP中,把职责定义为“变化的原因”。如果你能想到N个动机去改变一个类,那么这个类就具有多于一个的职责。这里说的“变化的原因”,只有实际发生时才 有意义。可能预测到会有多个原因引起这个类的变化,但这仅仅是预测,并没有真的发生,这个类仍可看做具有单一职责,不需要分离职责。
设计模式:
1.策略模式
定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
ps:这个其实就设置回调。
2.观察者模式
定义了对象之间的一对多依赖,这样以来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
ps:想想AS3的事件,当然事件机制比这个复杂。
3.装饰者模式
动态地将责任附加到对象上,若要扩展功能,装饰着提供了比继承更有弹性的替代方案。
ps:AS3的显示对象那种addChild的方式组合出来新的显示对象实际上就是一个装饰者模式,但是我也认为他是组合模式。
4.工厂方法模式
定义了一个创建对象的接口,但又子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
ps:为了避免抽象类和具体类耦合。
5.抽象工厂模式
提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确指定具体类。
ps:我们强调要针对接口编程,要依赖抽象等等,那么我们在哪里实例化具体的类?就在工厂里,工厂根据调用方的需求实例化出不同的具体类的对象来满足需求,这样以来你只需要在工厂里修改相应的实例化逻辑就能决定系统的模块配置了。另外能产生产品的工厂应该也是个具体类,但是由于抽象类不应该依赖具体类,所以我们让抽象类依赖一个抽象功能,在运行时将具体的工厂赋予它。
6.单例模式
确保一个类只有一个实例,并提供一个全局访问点。
ps:最简单的设计模式
7.命令模式
将请求封装成对象,以便使用不同的请求或者日志来参数话其他对象,命令模式也可支持撤销的操作。
ps:这和适配器模式有点像,但是更强调把不同的类都实现一个统一的命令接口供调用者统一调用。
8.适配器模式
将一个类的接口转换成客户期望的另外一个接口。适配器让原本接口不兼容的类可以合作无间。
ps:实际上就是一个兼容层。
9.外观模式
提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易被使用。
ps:这个玩意儿的意义参考最少知识原则。
10.模板方法模式
在一个方法定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
ps:关键是算法的骨架。
11.迭代器模式
提供一个方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
ps:这个模式的意义在于遍历一个集合,但是这个集合具体是什么结构可以不关心。这样以来我们可以任意替换数据结构而不影响遍历的代码。
12.组合模式
允许你将对象组合成树形结构来表现整体/部分层次结构。组合能让用户以一致的方式处理个别对象以及对象组合。
ps:就像AS3的现实列表机制。
13.状态模式
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
ps:这个有点像状态机,每个状态对应一个类,改变了状态则改变了当前执行的类。
14.代理模式
为另外一个对象提供一个替身或者占位符以控制对这个对象的访问。
ps:比如操作远程的数据就像操作本地的数据一样。