掌握设计模式

Published: 23 Oct 2015 Category: design_pattern

【喵体悟】书到用时方恨少,不要等到面试的时候才后悔没有好好准备!

阅读《The Zen of Design Patterns》

1、什么是设计模式?有什么好处?

作为一个经验总结,设计模式不是一个工具,它是软件开发的哲学,它能知道你如何去设计一个优秀的架构、编写一段健壮的代码、解决一个复杂的需求。

2、设计模式6大原则

分别是单一职责原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特原则和开闭原则。

2.1 Single Responsibility Principle

定义:有且仅有一个动作引起类的变更。

简单地来说,就是一个类里面的方法要实现职责分离。如一个用户信息类,应该作为UserBO和UserBiz两个类的组合类,使得其中的管理用户属性和负责用户行为的两个职责分离开来。(类似Model和Business分开)

好处:

  • 类的复杂度降低了,职责都有明确的定义;
  • 可读性提高
  • 可维护性提高
  • 变更引起的风险降低

该原则最难划分的就是职责,因为职责没有一个量化的标准。

该原则也可以用到方法上,不要通过参数让别人推测方法的功能,而应该在方法的命名上直接看出。

2.2 Liskov Substitution Principle

定义:只要父类出现的地方,子类就可以出现,而且替换子类也不会产生任何错误或异常。但是,反过来就不行,父类未必能替换子类。

详解:

  • 子类必须实现父类中的所有方法
  • 子类可以有自己的个性
  • 覆盖或实现父类的方法时输入参数可以被放大(如父类某个函数参数是HashMap,子类中的可以是Map)
  • 覆盖或实现父类的方法时输出结果可以被缩小(父类返回结果F和子类返回结果S存在关系:S要么和F是同一个类型,要么S是F的一个子类。)

采用里氏替换原则的目的是增强程序的健壮性

2.3 Dependence Inversion

理解:

  • 高层模块不应该依赖低层模块,两者应该依赖其抽象
  • 抽象不应该依赖细节
  • 细节应该依赖抽象

依赖倒置更近简洁的定义是——面向接口编程。

能减少类间的耦合性、提高系统的稳定性。降低并行开发引起的风险。

这个原则是最难实现的。它也是开闭原则实现的基础,没有它,就别想对扩展开放,对修改关闭。

2.4 接口隔离(Interface Segregation Principle)

定义:类间的依赖关系应该建立在最小的接口上。要建立单一接口,接口要细化,同时接口中的方法尽量少。

不要和单一职责原则相违背。

2.5 迪米特法则(Low of Demeter)

也叫最少知识原则——一个对象应该对其他对象有最少的了解。

Only talk to your immedate friends.

核心观念是类间的解耦。其要求的结果就是产生了大量的中转或跳转类,导致系统的复杂性提高,同时也给维护带来了难度。所以还是一个要根据实际情况进行权衡的原则。

2.6 开闭原则(Open Closed Principle)

对扩展开放,对修改关闭。

最基本的一个原则(开闭原则是抽象类,其他原则是实现类)

3、常见的设计模式例子

3.1 单例

在Spring中,每个Bean默认是单例的,这样做的优点是Spring容器可以管理这些Bean的生命周期。

如果采用非单例模式(Prototype类型),则Bean初始化后的管理交由J2EE容器,Spring容器将不再跟踪管理Bean的生命周期。

3.2 原型模式

不通过new关键字来产生一个对象,而是通过对象复制来实现的模式就叫原型模式。

实现这个模式:继承Cloneable接口,标示该类是可拷贝的。覆盖clone方法。

使用clone的时候,类的成员不要加final关键字。

3.3 策略模式

可以用在算术运算上。

缺点:所有的策略都需要暴露出去,供使用者选择。

3.4 组合模式

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

组合模式是对依赖倒置原则的破坏。

(你就想象成树结构,在xml的操作里面就存在这些优点: 所有节点都是Component,局部和整体对调用者来说没有任何区别;如果想增加树枝节点,只要找到父节点就可以快速增加)

现在的页面结构上、树形菜单、文件夹管理都是组合模式的思想所在。

3.5 门面模式

违背开闭原则。在后续对Facade对象需要改动的时候,没办法通过继承或者复写来完成,只能修改这个对象。

可以用在:对一个复杂的模块或子系统提供一个供外界访问的接口;子系统相对独立;预防低水平人员带来的风险扩散(让他们在指定的子系统或测试系统中开发,通过门面接口进行访问操作,其他人不必看实现代码,看也看不懂。)

3.6 访问者模式

违背了依赖倒置原则,访问者依赖的是具体元素,而不是抽象元素。

4、Java里面的文件读写用到了什么设计模式?

装饰器模式,对的。。

5、创建类模式比较

5.1 工厂方法和建造者

工厂方法模式注重的是整体对象的创建方法,创建者模式注重的是部件构建的过程,旨在一步一步地精确创建出一个复杂对象。

如创建机器人,工厂方法一下子就直接产生一个行走型机器人,而建造者模式需要组装手脚、头等部分。

5.2 抽象工厂方法和建造者

抽象工厂方法实现对产品家族的创建,一个产品家族是有这样的特点:具有不同分类维度的产品组合,该模式不关心构建过程,只关心什么产品由什么工厂产生。

建造者模式目的是通过组装零配件而产生一个新产品。

6、结构类模式比较

6.1 代理模式和装饰模式

装饰是代理模式的一个特殊应用,两者的共同点是具有同样的接口。不同的是,代理模式注重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,着重的是功能的变化。

6.2装饰模式和适配器模式

都是包装作用,都是通过委托的方式实现其功能。

不同:装饰模式包装的是自己的兄弟类,隶属于同一个家族;适配器模式则修饰非血缘关系类,把一个非家对象伪装成本家族对象。

装饰模式在任何时候都可以用,而适配器更像是一个补救模式,作为紧急手段使用。(意图和应用场景不同)

扩展性不同:前者更容易扩展,后者在两个不同的对象之间架起桥梁,去掉的过程会比较复杂。

7、行为类模式比较

7.1 命令模式和策略模式

命令模式多了一个接收者角色。 策略模式的意图是封装算法,让算法独立,并且可相互替换。 命令模式是对动作的解耦,把动作的执行分为执行对象(接收者角色)和执行行为(命令角色),让两者相互独立而不相互影响。

7.2 策略模式和状态模式

一个封装的是算法,一个封装的是状态,已达到状态切换行为随之发生改变的目的。

8、MVC框架

MVC通过Controller将View和Model进行分离,在处理请求时,控制器把请求转发模型M处理,模型从逻辑层和持久层获得返回结果,交由Controller,控制器根据结果组装视图,并最终反馈给浏览器可以接受的HTML数据。

MVC具有高重用性(多个模型可以共享一个视图,多个视图可以共享一个模型)、低耦合性(model和view分离)、快速开发和便捷部署(同时进行model和view的开发)

所用到的设计模式:

  • 策略模式——在MVC架构中,拦截来自不同源的文件,可以使用不同的算法进行处理。

  • 观察者模式——在配置文件被修改的时候,通知检查者进行处理。

  • 门面模式——对于模型管理器管理模型的过程,创建一个门面类,对不同的模型处理请求分发给不同的模型处理器。

  • 工厂方法——将所有拦截器链实现出来。

  • 还有责任链模式、迭代器模式、中介者模式(核心控制器为中心,其他同事类都负责为核心控制器“打工”)、访问者模式、代理模式等。


理解不了,就先记住。