洋蔥

贪婪,找不到比这更好的词了,是件好事。

上两节课中,我们学习了工厂模式,讲了工厂模式的应用场景,并带你实现了一个简单的DI容器。今天,我们再来学习另外一个比较常用的创建型设计模式,Builder模式,中文翻译为建造者模式或者构建者模式,也有人叫它生成器模式

实际上,建造者模式的原理和代码实现非常简单,掌握起来并不难,难点在于应用场景。比如,你有没有考虑过这样几个问题:直接使用构造函数或者配合set方法就能创建对象,为什么还需要建造者模式来创建呢?建造者模式和工厂模式都可以创建对象,那它们两个的区别在哪里呢?

话不多说,带着上面两个问题,让我们开始今天的学习吧!

阅读全文 »

在上一节课我们讲到,当创建对象是一个“大工程”的时候,我们一般会选择使用工厂模式,来封装对象复杂的创建过程,将对象的创建和使用分离,让代码更加清晰。那何为“大工程”呢?上一节课中我们讲了两种情况,一种是创建过程涉及复杂的if-else分支判断,另一种是对象创建需要组装多个其他类对象或者需要复杂的初始化过程。

今天,我们再来讲一个创建对象的“大工程”,依赖注入框架,或者叫依赖注入容器(Dependency Injection Container),简称DI容器。在今天的讲解中,我会带你一块搞清楚这样几个问题:DI容器跟我们讲的工厂模式又有何区别和联系?DI容器的核心功能有哪些,以及如何实现一个简单的DI容器?

话不多说,让我们正式开始今天的学习吧!

阅读全文 »

上几节课我们讲了单例模式,今天我们再来讲另外一个比较常用的创建型模式:工厂模式(Factory Design Pattern)。

一般情况下,工厂模式分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。不过,在GoF的《设计模式》一书中,它将简单工厂模式看作是工厂方法模式的一种特例,所以工厂模式只被分成了工厂方法和抽象工厂两类。实际上,前面一种分类方法更加常见,所以,在今天的讲解中,我们沿用第一种分类方法。

在这三种细分的工厂模式中,简单工厂、工厂方法原理比较简单,在实际的项目中也比较常用。而抽象工厂的原理稍微复杂点,在实际的项目中相对也不常用。所以,我们今天讲解的重点是前两种工厂模式。对于抽象工厂,你稍微了解一下即可。

除此之外,我们讲解的重点也不是原理和实现,因为这些都很简单,重点还是带你搞清楚应用场景:什么时候该用工厂模式?相对于直接new来创建对象,用工厂模式来创建究竟有什么好处呢?

话不多说,让我们正式开始今天的学习吧!

阅读全文 »

上两节课中,我们针对单例模式,讲解了单例的应用场景、几种常见的代码实现和存在的问题,并粗略给出了替换单例模式的方法,比如工厂模式、IOC容器。今天,我们再进一步扩展延伸一下,一块讨论一下下面这几个问题:

  • 如何理解单例模式中的唯一性?
  • 如何实现线程唯一的单例?
  • 如何实现集群环境下的单例?
  • 如何实现一个多例模式?

今天的内容稍微有点“烧脑”,希望你在看的过程中多思考一下。话不多说,让我们正式开始今天的学习吧!

阅读全文 »

上一节课中,我们通过两个实战案例,讲解了单例模式的一些应用场景,比如,避免资源访问冲突、表示业务概念上的全局唯一类。除此之外,我们还学习了Java语言中,单例模式的几种实现方法。如果你熟悉的是其他编程语言,不知道你课后有没有自己去对照着实现一下呢?

尽管单例是一个很常用的设计模式,在实际的开发中,我们也确实经常用到它,但是,有些人认为单例是一种反模式(anti-pattern),并不推荐使用。所以,今天,我就针对这个说法详细地讲讲这几个问题:单例这种设计模式存在哪些问题?为什么会被称为反模式?如果不用单例,该如何表示全局唯一类?有何替代的解决方案?

话不多说,让我们带着这些问题,正式开始今天的学习吧!

阅读全文 »

从今天开始,我们正式进入到设计模式的学习。我们知道,经典的设计模式有23种。其中,常用的并不是很多。据我的工作经验来看,常用的可能都不到一半。如果随便抓一个程序员,让他说一说最熟悉的3种设计模式,那其中肯定会包含今天要讲的单例模式。

网上有很多讲解单例模式的文章,但大部分都侧重讲解,如何来实现一个线程安全的单例。我今天也会讲到各种单例的实现方法,但是,这并不是我们专栏学习的重点,我重点还是希望带你搞清楚下面这样几个问题(第一个问题会在今天讲解,后面三个问题放到下一节课中讲解)。

  • 为什么要使用单例?
  • 单例存在哪些问题?
  • 单例与静态类的区别?
  • 有何替代的解决方案?

话不多说,让我们带着这些问题,正式开始今天的学习吧!

阅读全文 »

上一节课中,我们针对版本1存在的问题(特别是Aggregator类、ConsoleReporter和EmailReporter类)进行了重构优化。经过重构之后,代码结构更加清晰、合理、有逻辑性。不过,在细节方面还是存在一些问题,比如ConsoleReporter、EmailReporter类仍然存在代码重复、可测试性差的问题。今天,我们就在版本3中持续重构这部分代码。

除此之外,在版本3中,我们还会继续完善框架的功能和非功能需求。比如,让原始数据的采集和存储异步执行,解决聚合统计在数据量大的情况下会导致内存吃紧问题,以及提高框架的易用性等,让它成为一个能用且好用的框架。

话不多说,让我们正式开始版本3的设计与实现吧!

阅读全文 »

第25节第26节中,我们讲了如何对一个性能计数器框架进行分析、设计与实现,并且实践了之前学过的一些设计原则和设计思想。当时我们提到,小步快跑、逐步迭代是一种非常实用的开发模式。所以,针对这个框架的开发,我们分多个版本来逐步完善。

在第25、26节课中,我们实现了框架的第一个版本,它只包含最基本的一些功能,在设计与实现上还有很多不足。所以,接下来,我会针对这些不足,继续迭代开发两个版本:版本2和版本3,分别对应第39节和第40节的内容。

在版本2中,我们会利用之前学过的重构方法,对版本1的设计与实现进行重构,解决版本1存在的设计问题,让它满足之前学过的设计原则、思想、编程规范。在版本3中,我们再对版本2进行迭代,并且完善框架的功能和非功能需求,让其满足第25节课中罗列的所有需求。

话不多说,让我们正式开始版本2的设计与实现吧!

阅读全文 »

到今天为止,设计原则和思想已经全部讲完了,其中包括:面向对象、设计原则、规范与重构三个模块的内容。除此之外,我们还学习了贯穿整个专栏的代码质量评判标准。专栏的进度已经接近一半,马上就要进入设计模式内容的学习了。在此之前,我先带你一块来总结回顾一下,我们已经学过的所有知识点。

今天的内容比较多,有一万多字,但都是之前学过的,算是一个总结回顾,主要是想带你复习一下,温故而知新。如果你看了之后,感觉都有印象,那就说明学得还不错;如果还能在脑子里形成自己的知识架构,闭上眼睛都能回忆上来,那说明你学得很好;如果能有自己的理解,并且在项目开发中,开始思考代码质量问题,开始用已经学过的设计原则和思想来审视代码,那说明你已经掌握这些内容的精髓。

阅读全文 »

平时进行软件设计开发的时候,我们除了要保证正常情况下的逻辑运行正确之外,还需要编写大量额外的代码,来处理有可能出现的异常情况,以保证代码在任何情况下,都在我们的掌控之内,不会出现非预期的运行结果。程序的bug往往都出现在一些边界条件和异常情况下,所以说,异常处理得好坏直接影响了代码的健壮性。全面、合理地处理各种异常能有效减少代码bug,也是保证代码质量的一个重要手段。

在上一节课中,我们讲解了几种异常情况的处理方式,比如返回错误码、NULL值、空对象、异常对象。针对最常用的异常对象,我们还重点讲解了两种异常类型的应用场景,以及针对函数抛出的异常的三种处理方式:直接吞掉、原封不动地抛出和包裹成新的异常抛出。

除此之外,在上一节课的开头,我们还针对ID生成器的代码,提出了4个有关异常处理的问题。今天,我们就用一节课的时间,结合上一节课讲到的理论知识,来逐一解答一下这几个问题。

话不多说,让我们正式开始今天的内容吧!

阅读全文 »
0%