最初接触模式的时候是在培训的时候,那个时候培训的老师大谈MVC,但仅仅知道这是一种强大的架构,对其他的一无所知。
最初对java模式有一些些概念是在面试的时候,我至今还清晰的记得那个文思创新的面试我的中年人,上来直接问我:学过模式没,知道常用的几种模式吗?能够写并且谈论一下你的感受吗?我一下子有的只是无语,然后是恢恢而去。
最初对java模式有了一定的了解是在工作后的一段时间,来源于那个移动阅读的手机项目。它采用的就是MVC架构:N多的页面View;N多的实体modal;唯一的一个控制器Controller。控制器负责页面之间关系的维护,加载和释放资源的统一调度。这个唯一的一个控制器采用的显然是单例模式;另外页面的注册类用的是最简单的简单工厂模式。
其中我最有印象的无疑是观察者模式。具体在另一边博文java接口与模式(观察者)中有讲到。
那么究竟什么是模式?
一个围棋下的好的人知道,好的“形”对于围棋非常重要。形是棋子在棋盘上的几何形状的抽象化。形就是模式(pattern),也是人脑把握和认识外界的关键。模式化的过程是把问题抽象化,在忽略掉不重要的细节后,发现问题的一般性本质,并找到普遍适用的解决方案的过程。
简而言之,人们在自己的环境中不断发现问题和寻找问题的解决方案的时候,发现有一些问题及其解决方案不断变换面孔重复出现,但在这些不同的面孔后面有着相同的本质,这些共同的本质就是模式。
设计的原则:
1.开---闭 原则:一个软件实体应当对扩展开放,对修改关闭。这个原则说的是,在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。换言之,应当可以在不修改源代码的情况下改变这个模块的行为。
实现开---闭原则的关键在于抽象化。像在面向对象的编程语言中,可以给系统定义出一个一劳永逸,不再修改的抽象设计,此设计允许无穷无尽的行为在实现层被实现。java里面可以给出一个或多个抽象java类或java接口,规定出所有具体类必须实现的方法特征作为系统设计的抽象层。这个抽象层预见了所有的可能扩展,因此在任何情况下都不会改变。这就使得系统的抽象层不再需要修改,满足开---闭原则第二条:对修改关闭。同时,由于从抽象层导出一个或多个新的具体类,可以改变系统的行为,因此系统的设计对扩展开放,满足第一条。
2.里氏代换原则:任何基类出现的地方,子类都可以出现。它是对开--闭原则的补充。实现开---闭原则的关键就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
3.依赖倒转原则:要依赖于抽象,不要依赖于实现。开--闭原则是目标,依赖倒转原则是手段。
4.合成/聚合复用原则:要尽量使用合成/聚合原则,而不是继承关系达到复用的目的。这个原则建议你要小心仔细使用继承。要区分"has "与"in"的区别,当一个类是另一个类的角色时,不应当使用继承来描述这种关系,而应该使用合成/聚合复用。只有当一下条件全部满足时,才是使用继承的最佳时机:1.子类是超类的一个特殊种类,而不是超类的一个角色。2.永远不会出现需要将子类换成另一个类的子类的情况。3.子类具有扩展超类的责任,而不是仅仅置换(override)超类的责任。4.只有在分类学角度上有意义时,才可以使用继承,不要从工具类继承。
封装模式是其的一个应用,java API中的各种数据流才封装就采用的这种模式。
5.迪米特法则:一个软件实体应当与尽可能少的其他实体发生相互作用。这要求我们尽量做到耦合的分离。门面模式是它的一个应用。
6.接口隔离原则:应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口。显然,它与迪米特法则都是对一个软件实体与其他软件实体的通信的限制。遵循接口隔离和迪米特法则,会使一个软件系统在功能扩展的过程中,不会将修改的压力传到其他对象。这个原则我的一篇博文也有详细阐述。
最初对java模式有一些些概念是在面试的时候,我至今还清晰的记得那个文思创新的面试我的中年人,上来直接问我:学过模式没,知道常用的几种模式吗?能够写并且谈论一下你的感受吗?我一下子有的只是无语,然后是恢恢而去。
最初对java模式有了一定的了解是在工作后的一段时间,来源于那个移动阅读的手机项目。它采用的就是MVC架构:N多的页面View;N多的实体modal;唯一的一个控制器Controller。控制器负责页面之间关系的维护,加载和释放资源的统一调度。这个唯一的一个控制器采用的显然是单例模式;另外页面的注册类用的是最简单的简单工厂模式。
其中我最有印象的无疑是观察者模式。具体在另一边博文java接口与模式(观察者)中有讲到。
那么究竟什么是模式?
一个围棋下的好的人知道,好的“形”对于围棋非常重要。形是棋子在棋盘上的几何形状的抽象化。形就是模式(pattern),也是人脑把握和认识外界的关键。模式化的过程是把问题抽象化,在忽略掉不重要的细节后,发现问题的一般性本质,并找到普遍适用的解决方案的过程。
简而言之,人们在自己的环境中不断发现问题和寻找问题的解决方案的时候,发现有一些问题及其解决方案不断变换面孔重复出现,但在这些不同的面孔后面有着相同的本质,这些共同的本质就是模式。
设计的原则:
1.开---闭 原则:一个软件实体应当对扩展开放,对修改关闭。这个原则说的是,在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。换言之,应当可以在不修改源代码的情况下改变这个模块的行为。
实现开---闭原则的关键在于抽象化。像在面向对象的编程语言中,可以给系统定义出一个一劳永逸,不再修改的抽象设计,此设计允许无穷无尽的行为在实现层被实现。java里面可以给出一个或多个抽象java类或java接口,规定出所有具体类必须实现的方法特征作为系统设计的抽象层。这个抽象层预见了所有的可能扩展,因此在任何情况下都不会改变。这就使得系统的抽象层不再需要修改,满足开---闭原则第二条:对修改关闭。同时,由于从抽象层导出一个或多个新的具体类,可以改变系统的行为,因此系统的设计对扩展开放,满足第一条。
2.里氏代换原则:任何基类出现的地方,子类都可以出现。它是对开--闭原则的补充。实现开---闭原则的关键就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
3.依赖倒转原则:要依赖于抽象,不要依赖于实现。开--闭原则是目标,依赖倒转原则是手段。
4.合成/聚合复用原则:要尽量使用合成/聚合原则,而不是继承关系达到复用的目的。这个原则建议你要小心仔细使用继承。要区分"has "与"in"的区别,当一个类是另一个类的角色时,不应当使用继承来描述这种关系,而应该使用合成/聚合复用。只有当一下条件全部满足时,才是使用继承的最佳时机:1.子类是超类的一个特殊种类,而不是超类的一个角色。2.永远不会出现需要将子类换成另一个类的子类的情况。3.子类具有扩展超类的责任,而不是仅仅置换(override)超类的责任。4.只有在分类学角度上有意义时,才可以使用继承,不要从工具类继承。
封装模式是其的一个应用,java API中的各种数据流才封装就采用的这种模式。
5.迪米特法则:一个软件实体应当与尽可能少的其他实体发生相互作用。这要求我们尽量做到耦合的分离。门面模式是它的一个应用。
6.接口隔离原则:应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口。显然,它与迪米特法则都是对一个软件实体与其他软件实体的通信的限制。遵循接口隔离和迪米特法则,会使一个软件系统在功能扩展的过程中,不会将修改的压力传到其他对象。这个原则我的一篇博文也有详细阐述。