
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
单例模式是软件开发程序员在开发软件的时候会经常用到的一种设计模式,而本文我们就通过案例分析来简单了解一下,单例模式设计应用都有哪些不足之处。
1、隐藏类之间依赖
代码的可读性非常重要。在阅读代码的时候,我们希望一眼就能看出类与类之间的依赖关系,搞清楚这个类依赖了哪些外部类。通过构造函数、参数传递等方式声明的类之间的依赖关系,我们通过查看函数的定义,就能很容易识别出来。但是,单例类不需要显示创建、不需要依赖参数传递,在函数中直接调用就可以了。如果代码比较复杂,这种调用关系就会非常隐蔽。在阅读代码的时候,我们就需要仔细查看每个函数的代码实现,才能知道这个类到底依赖了哪些单例类。
2、代码扩展性不友好
单例类只能有一个对象实例。如果未来某一天,我们需要在代码中创建两个实例或多个实例,那就要对代码有比较大的改动。你可能会说,会有这样的需求吗?既然单例类大部分情况下都用来表示全局类,怎么会需要两个或者多个实例呢?
在系统设计初期,我们觉得系统中只应该有一个数据库连接池,这样能方便我们控制对数据库连接资源的消耗。所以,我们把数据库连接池类设计成了单例类。但之后我们发现,系统中有些SQL语句运行得非常慢。这些SQL语句在执行的时候,长时间占用数据库连接资源,导致其他SQL请求无法响应。为了解决这个问题,我们希望将慢SQL与其他SQL隔离开来执行。为了实现这样的目的,我们可以在系统中创建两个数据库连接池,慢SQL独享一个数据库连接池,其他SQL独享另外一个数据库连接池,这样就能避免慢SQL影响到其他SQL的执行。
如果我们将数据库连接池设计成单例类,显然就无法适应这样的需求变更,也就是说,单例类在某些情况下会影响代码的扩展性、灵活性。所以,数据库连接池、线程池这类的资源池,好还是不要设计成单例类。实际上,一些开源的数据库连接池、线程池也确实没有设计成单例类。
3、可测试性不友好
单例模式的使用会影响到代码的可测试性。如果单例类依赖比较重的外部资源,比如DB,我们在写单元测试的时候,希望能通过mock的方式将它替换掉。而单例类这种硬编码式的使用方式,导致无法实现mock替换。
除此之外,如果单例类持有成员变量(比如IdGenerator中的id成员变量),那它实际上相当于一种全局变量,被所有的代码共享。如果这个全局变量是一个可变全局变量,也就是说,它的成员变量是可以被修改的,那我们在编写单元测试的时候,还需要注意不同测试用例之间,修改了单例类中的同一个成员变量的值,从而导致测试结果互相影响的问题。
4、不支持有参构造函数
单例不支持有参数的构造函数,比如我们创建一个连接池的单例对象,我们没法通过参数来指定连接池的大小。针对这个问题,我们来看下都有哪些解决方案。
一种解决思路是:创建完实例之后,再调用init()函数传递参数。需要注意的是,我们在使用这个单例类的时候,要先调用init()方法,然后才能调用getInstance()方法,否则代码会抛出异常。
【免责声明】本文系本网编辑部分转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与管理员联系,我们会予以更改或删除相关文章,以保证您的权益!更多内容请加danei0707学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。