比较巧,自己在接触设计模式的时候,也刚开始学习spring,但可惜的是,真的仅仅在学习“用”spring,每天都沉浸在会痛快的完成spring各种配置的快乐之中,但对成长无用。其实当初就清楚,spring框架中有大量设计模式,于是也下了代码来看,设计模式其实没那么简单,当初的学习也很皮毛,所以就没有发现spring中的金矿。现在动手,里面依然还是金矿,但不要偷懒,让它完全腐烂。[这是对自己的告诫]

开头上来就说到了spring跟设计模式,实际上,spring中的核心原则就是基于设计模式来构建的。这个时候继续祭出《敏捷软件开发》这本神书,结合里面比较全面的和具体的设计模式来大体讨论一下各种设计模式。(在此也建议将《敏捷》多看几遍,虽然里面用了c++示例,但极易理解)

在学习和讨论每种设计模式之前,都应该明确这样几个问题:

1)这个模式是什么?

2)这个模式适应的场景是什么,有何限制?

3)《敏捷》里面是如何推出来用这个模式的?针对《敏捷》中的场景,如若不考虑这个模式,会如何出手?这种类似于范伟大师傅的神功,为何降服不了“黑帮”?铁定被打趴在地上的原因,有考虑过么?[范伟是俺的偶像]

Command模式

这个模式表面上看是个比较简单的模式,这个是Bob的看法。他强调Command模式具有“功能分解的味道”。实际上在《design patterns》里面command也是被归类在行为类的。一般的command接口定义:

public interface Command {

public void do();

}

从这个接口的角度讲,我们根本不知道它的主要意图是什么,所以在一个类实现这个接口之后,这个类的动作意图,也同样被这个接口给封装起来了。Bob认为从面向对象角度,这是违犯天条的行为。但从上层抽象来说,这又是很好的屏蔽了上层(caller)对具体实现的依赖。所以说,命令模式是一种面向动作的独立抽象,它可以很好地处理输入和动作调用方之间的隔离关系。

考虑到《敏捷》中的两个例子,例1复印机程序,传感器可以在不需要知道当前的事件具体是什么的前提下,直接调用绑定到事件上的command 接口方法。例2验证雇员信息合法性的实现。在增加每个雇员信息到数据库之前都有对其所有信息的合法性进行验证。雇佣方式不同的雇员,其相关信息也是不一样的。如按小时工作的员工需要有相关的时间信息,而按业绩支付的也需要有相应的时间和数量,按月支付的员工则没有额外的信息。但在做增加一个雇员信息的事务时,能隔离掉对具体信息的依赖,可以减少这个事务代码实现的复杂性。《敏捷》在网上有电子书,各位可以对照着看看具体的架构实现。

针对《敏捷》中雇员事务的实现,来说明一种可能比较常见的方法,首先声明,这里说明的方法,从一定意义上讲,是没有考虑面向对象这些设计的,而是我们经常随手拈来写代码凑出来的习惯,写在这里,是想提醒自己,以后碰到这样的场景,应该考虑一下设计模式。看到这个需求,我们的第一印象,应该是给雇员分类:

public enum EmployeeType {

HOUR(1),

MONTH(2),

COMMISSION(3);

private EmployeeType(int type){

this.type = type;

}

private int type;

public int getValue(){

return this.type;

}

}

然后在实现AddEmployeeTransaction时,判断加入的Employee的type. 跟Bob的实现相比,我们少了什么,又多了什么?我的答案肯定不是唯一的,不仅是对这个需求的实现,还有前面这个问题。我来说一下自己的看法:

1.过程性的思维定势,使得AddEmployeeTransaction需要了解全部的可能情况,在种类繁多的情况下,可能会出现一个极其庞大,充满了if-else的大方法;

2.因为第一点,我们肯定创建了一个极其简单POJO 对象,很多人都会直接命名成VO(ValueObject)。

于是,各种所谓的smell就会出现。那么这个时候,我们可能通过重构来抽取出一些小方法,来格式化一个庞大的方法。如此之多的方法是否在说明一个问题,一些行为是否可以形成抽象。因为我们知道if-else比较多的情况下,要考虑command,strategy之类的设计模式,为什么?因为这些模式都是面向行为的,而我们就是在针对行为进行重构。

想到这里,突然对《重构》这本人人喜爱的书有点惋惜,要是它里面能关联上设计模式方面的内容,可能会更具震撼力,因为行动加上理论依据更有说服力,也可以在总是学重构方法方式的时候能思考一下,什么样的重构推出来什么样的模式。

以上是我的个人见解,是做了7,8年的一个对自己编码方式的总结,后面的一些设计模式,也会带上个人色彩的自我剖析。

那么为什么要讲command模式,当然接这个机会都学一遍,但在《设计模式》中关于Command模式的应用部分,其中的一种方式就是采用callback的方式来提供action perform,从而在时间上和引用上都隔离request和调用者。spring里面在阐述IoC的时候,尤其是关于jdbc的封装,它将具体业务相关的动作放到一个callback对象中,而JdbcTemplate可以在毫不关心具体业务动作的状况下,进行调用。

希望这个关联,有助于加深对spring设计的理解。

在part2,再讨论其他几个相关的设计模式,或许多少都会提一下。《设计模式》,《敏捷》,《Expert》这三本书再次捧在手上还是引人入胜,只是现在不会再像以前那么急躁,那么不顾实际场景的使用。由于spring这个框架本身就是个集大成的模板,这是一个极好的机会能切实看到大师级的架构思路,所以后面看情况,如有必要,就一下子把设计模式都过一遍。

Dive into Spring framework -- 了解基本原理(二)--设计模式-part1的更多相关文章

  1. Dive into Spring framework -- 了解基本原理(一)

    在继续我们的分析之前,推荐各位静心来读一下<<Expert_OneOne_J2EE_Design_and_Development>> 第四章, 正如spring BeanFac ...

  2. Dive into Spring framework -- 了解基本原理(二)--设计模式-part2

    Template模式 Template模式顾名思义是提供了一种模板,也就是针对某种业务提供了模范框架.这个在spring中是属于核心模式的,因为其ApplicationContext抽象类就是模板模式 ...

  3. Dive into Spring framework -- 搭建spring 源码的开发环境

    spring是一个类之间依赖的管理容器,大家都知道,但我们中很多人都仅仅停留在使用的层面,但spring本身具有极大的研究价值,所以在使用了几年spring之后,还是想深入的探究一下其根源.记录于此, ...

  4. Spring Boot 启动(二) 配置详解

    Spring Boot 启动(二) 配置详解 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Boot 配置 ...

  5. Spring Framework简介

    作者关于此主题早期文章 Spring框架快速入门 起源 要谈Spring的历史,就要先谈J2EE.J2EE应用程序的广泛实现是在1999年和2000年开始的,它的出现带来了诸如事务管理之类的核心中间层 ...

  6. 设计模式学习(二十四):Spring 中使用到的设计模式

    设计模式学习(二十四):Spring 中使用到的设计模式 作者:Grey 原文地址: 博客园:设计模式学习(二十四):Spring 中使用到的设计模式 CSDN:设计模式学习(二十四):Spring ...

  7. Spring Framework 官方文档学习(四)之Validation、Data Binding、Type Conversion(二)

    接前一篇 Spring Framework 官方文档学习(四)之Validation.Data Binding.Type Conversion(一) 本篇主要内容:Spring Type Conver ...

  8. 框架应用:Spring framework (一) - IoC技术

    IoC概念以及目标 IoC就是让原本你自己管理的对象交由容器来进行管理,其主要的目的是松耦合. IoC发展史 既然IoC的目标是为了松耦合,那它怎么做到的? 最后目标:降低对象之间的耦合度,IoC技术 ...

  9. Spring Framework(框架)整体架构 变迁

    Spring Framework(框架)整体架构 2018年04月24日 11:16:41 阅读数:1444 标签: Spring框架架构 更多 个人分类: Spring框架   版权声明:本文为博主 ...

随机推荐

  1. #define宏定义

    1 #define的概念  #define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本.  该命令有两种格式:一种是简单的宏定义, ...

  2. HTTP API 设计指南(转)

    add by zhj (2014-12-16): 今天才知道,原画HeroKu是国外一个很有名的PaaS提供商,公司很可能会将app迁移到他们那里 英文原文: HTTP API Design Guid ...

  3. understand EntityManager.joinTransaction()

    Join Transaction The EntityManager.joinTransaction() API allows an application managed EntityManager ...

  4. git提交到远程虚拟机

    git到自己的虚拟机中第一步:打通git(一)Linux中(ip为10.1.8.1)1.安装git如:Ubuntu中安装gitapt install git 2.Ubuntu中添加git用户sudo ...

  5. sqlserver表结构查询语句

    SELECT syscolumns.name,systypes.name,syscolumns.isnullable,syscolumns.length FROM syscolumns, systyp ...

  6. jquery Chosen使用

    1,首先去http://harvesthq.github.io/chosen/下载插件. 2,在网页中加入下面的文件. <link rel="stylesheet" href ...

  7. 基于nodejs的websocket通信程序设计

    网络程序设计无疑是nodejs + html最好用 一.nodejs的安装 1.在ubuntu上的安装 sudo apt install nodejs-legacy sudo apt install ...

  8. php内存溢出,出现Allowed memory size of 8388608 bytes exhausted错误的解决办法

    是因为php页面消耗的最大内存默认是为128M (在PHP的ini件里可以看到) ,如果文件太大或图片太大在读取的时候会发生上述错误. 解决办法: 1.修改 php.ini 将memory_limit ...

  9. 浅析selenium的PageFactory模式 PageFactory初始化pageobject

    1.首先介绍FindBy类: For example, these two annotations point to the same element: @FindBy(id = "foob ...

  10. 08 网络配置、shh服务、bash命令和元字符

    作业一:完成作业未做完的集群架构作业二:临时配置网络(ip,网关,dns)+永久配置 作业三:为集群内的机器设定主机名,利用/etc/hosts文件来解析自己的集群中所有的主机名,相应的,集群的配置应 ...