`
gamix
  • 浏览: 1856 次
  • 来自: ...
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

如此使用单例模式!

阅读更多
最近拿到一个项目,大致扫了一下,发现大多数的代码都是如下的结构:

public class User {
	private String userName;
	
	public String getUserName() {
		return userName;
	}
	
	public void setUserName(String userName) {
		this.userName = userName;
	}
}

public class UserRule { 
	private static UserRule instance = null; 
	
	public static UserRule getInstance() { 
		if (instance == null) { 
			instance = new UserRule(); 
		} 
		return instance; 
	}
	
	public User AddUser(String userName) {
		// add a new user operations
	}
} 


先不说问题,来看看这样做的一些可取之处:
1、设计简单。系统的设计在这样的结构下其实就是贫血类的设计,剩下的就是在Rule类中增加相应的方法。
2、各个模块的开发可以同时进行。各人根据要求定义好模块相应的类,剩下的就是缺啥补啥了。

然后说问题:
1、首先该单例实现就有问题了,这样的实现并不能保证线程安全。不过好在其实这个UserRule本身也没有字段之类的东西,不单例其实也没多大影响。所以我想这个单例丢在这里估计只是为了写代码的时候方便点。
2、这种做法应对需求变化的结果就是不断的在UserRule中添加新的满足需求的方法,最后天知道这个方法到底干嘛的。
3、我想这样的系统应该性能上很差了,可奇怪客户用到现在居然没一点性能上的反馈。不过性能这块只是我的一个感觉,还没有对这样的系统做一个压力测试,无法提供实际情况。

不知道还有没有其他的缺点,欢迎各位来分析分析。
分享到:
评论
68 楼 awdxzc 2009-02-11  
我想请问这里用单例有什么用? 而且单例还写错了,性能方面我觉得应该差不多,但是这样写是线程不安全的。
67 楼 hecan8110 2009-02-11  
楼主的示例不是单例模式啊
66 楼 dandy 2009-02-11  
怎么看不出和单例有什么关系。
65 楼 weick 2009-02-10  
czqyr 写道
它不是单例模式已经知道了
但我对线程安全不太懂。。。
有什么推荐的文章看一看吗?


我觉得 thinking in java 讲的不错。
64 楼 eagle8625 2009-02-10  
ferry2174 写道
单例的意思就是说在应用程序中只存在一个此类的实例,不管使用什么方法,能保证这个条件就是单例,没必要非得按照什么格式来写。一个单例中只要没有全局变量,那么在业务处理时也就没什么线程不安全的问题,问题只是存在第一次调用getInstance()方法时,大不了在系统加载时就调用此类的getInstance()方法,就自然不会产生线程安全的问题。JAVA程序的性能瓶颈大多在数据库,我想我不会在乎使用synchronized这0.1秒的性能损失的,而且这0.1秒不知道可以创建一个多么大的对象了。

这个单例在使用上的问题在于楼主说的“贫血设计”上。UserRule这个类看起来应该是个session类,不同于一般“util”类,它是负责业务操作的。如果程序很简单、规则是单一的这么写也无可厚非。一旦碰到稍微复杂的业务逻辑,不能使用多态那么对依赖于此类的其他类维护起来就是灾难性的,所谓的发散式修改会一直伴随在这个类的生命周期中。以上只是在假定此类是业务处理类而非工具类的基础上做出,要从设计的角度来评价这个类的好坏还得看他在应用中所处的位置和所起的作用,这是楼主没有给的。

从这个类中我并没看出什么性能问题来,这样设计会让此类在应用生命周期中只创建一次,能提升性能。真正的性能问题要综合全局来看才能有结论。


在单粒模式下,不同的线程如何通过相同的实例找到各自的局部变量值啊?
63 楼 james.zhou 2009-02-10  
好像这个单例 缺少私有的构造器啊!
62 楼 newjavaeyeuser 2009-02-09  
zozoh 是标准的教科书写法  可以解决多线程问题
61 楼 Laynepeng 2009-02-05  
双重检查成例现在JVM已经可以支持了吗?以前是不可以的,见[BLOCH01,GOETZ01,DCL01]
60 楼 skyfaint 2009-02-04  
pipilu 写道
vampire423 写道
zozoh 写道
#     public static UserRule getInstance() {  
#         if (instance == null) {  
#             instance = new UserRule();  
#         }  
#         return instance;  
#     }

应该写成
public static UserRule getInstance() {  
if (instance == null) {
synchronized(UserRule.class){
if (instance == null){
instance = new UserRule();
}
}
}  
return instance;  
}

以保证多个线程访问的安全



Java中使用单例模式中必须像这样进行双重检查,否则会出现多线程问题


太扯了。
双重检查只是为了避免以后访问此方法时的性能问题——因为只有第一次创建实例时,才需要同步锁。
自己看看去吧:http://www.ibm.com/developerworks/cn/java/j-dcl.html


59 楼 boboism 2009-02-04  
我刚开始学设计模式,但是觉得更像是简单工厂,最起码UserRule的Constructor没有私有化。
58 楼 gordonAtJava 2009-02-03  
ferry2174 写道
单例的意思就是说在应用程序中只存在一个此类的实例,不管使用什么方法,能保证这个条件就是单例,没必要非得按照什么格式来写。一个单例中只要没有全局变量,那么在业务处理时也就没什么线程不安全的问题,问题只是存在第一次调用getInstance()方法时,大不了在系统加载时就调用此类的getInstance()方法,就自然不会产生线程安全的问题。JAVA程序的性能瓶颈大多在数据库,我想我不会在乎使用synchronized这0.1秒的性能损失的,而且这0.1秒不知道可以创建一个多么大的对象了。

这个单例在使用上的问题在于楼主说的“贫血设计”上。UserRule这个类看起来应该是个session类,不同于一般“util”类,它是负责业务操作的。如果程序很简单、规则是单一的这么写也无可厚非。一旦碰到稍微复杂的业务逻辑,不能使用多态那么对依赖于此类的其他类维护起来就是灾难性的,所谓的发散式修改会一直伴随在这个类的生命周期中。以上只是在假定此类是业务处理类而非工具类的基础上做出,要从设计的角度来评价这个类的好坏还得看他在应用中所处的位置和所起的作用,这是楼主没有给的。

从这个类中我并没看出什么性能问题来,这样设计会让此类在应用生命周期中只创建一次,能提升性能。真正的性能问题要综合全局来看才能有结论。


看到说到点子上的了

另外在这个例子里面贫血也没有什么不好的
57 楼 usiboy 2009-02-02  
ych516 写道
kimmking 写道
引用
性能是测试出来的 不是你想出来的


赞这句


同意哈~

继续支持
56 楼 maxwell 2009-02-02  
好像不是单例吧, 你再理解理解?
55 楼 pipilu 2009-01-31  
vampire423 写道
zozoh 写道
#     public static UserRule getInstance() {  
#         if (instance == null) {  
#             instance = new UserRule();  
#         }  
#         return instance;  
#     }

应该写成
public static UserRule getInstance() {  
if (instance == null) {
synchronized(UserRule.class){
if (instance == null){
instance = new UserRule();
}
}
}  
return instance;  
}

以保证多个线程访问的安全



Java中使用单例模式中必须像这样进行双重检查,否则会出现多线程问题


太扯了。
双重检查只是为了避免以后访问此方法时的性能问题——因为只有第一次创建实例时,才需要同步锁。
自己看看去吧:http://www.ibm.com/developerworks/cn/java/j-dcl.html

54 楼 rascalx 2009-01-31  
看来你对单例的认识太简单了.
53 楼 vampire423 2009-01-30  
zozoh 写道
#     public static UserRule getInstance() {  
#         if (instance == null) {  
#             instance = new UserRule();  
#         }  
#         return instance;  
#     }

应该写成
public static UserRule getInstance() {  
if (instance == null) {
synchronized(UserRule.class){
if (instance == null){
instance = new UserRule();
}
}
}  
return instance;  
}

以保证多个线程访问的安全



Java中使用单例模式中必须像这样进行双重检查,否则会出现多线程问题
52 楼 p.p0714 2009-01-29  
精神可嘉!
51 楼 ferry2174 2009-01-27  
单例的意思就是说在应用程序中只存在一个此类的实例,不管使用什么方法,能保证这个条件就是单例,没必要非得按照什么格式来写。一个单例中只要没有全局变量,那么在业务处理时也就没什么线程不安全的问题,问题只是存在第一次调用getInstance()方法时,大不了在系统加载时就调用此类的getInstance()方法,就自然不会产生线程安全的问题。JAVA程序的性能瓶颈大多在数据库,我想我不会在乎使用synchronized这0.1秒的性能损失的,而且这0.1秒不知道可以创建一个多么大的对象了。

这个单例在使用上的问题在于楼主说的“贫血设计”上。UserRule这个类看起来应该是个session类,不同于一般“util”类,它是负责业务操作的。如果程序很简单、规则是单一的这么写也无可厚非。一旦碰到稍微复杂的业务逻辑,不能使用多态那么对依赖于此类的其他类维护起来就是灾难性的,所谓的发散式修改会一直伴随在这个类的生命周期中。以上只是在假定此类是业务处理类而非工具类的基础上做出,要从设计的角度来评价这个类的好坏还得看他在应用中所处的位置和所起的作用,这是楼主没有给的。

从这个类中我并没看出什么性能问题来,这样设计会让此类在应用生命周期中只创建一次,能提升性能。真正的性能问题要综合全局来看才能有结论。

50 楼 fisher126 2009-01-27  
楼主的根本谈不上单例,楼上的是正解。
49 楼 nba520pz 2009-01-24  
这个不是单例模式,正确的写法应该是这样的:
public class UserRule {   
    private static volatile UserRule instance = null;   
    private static Object o=new Object();
    private UserRule (){}//构造方法必须是私有的
    public static UserRule getInstance() {   
        if (instance == null) {  
            synchronized(o){
               if(instance == null){
                  instance = new UserRule();   
               }
            }           
        }//两次检查,确保线程安全   
        return instance;   
    }  
      
    public User AddUser(String userName) {  
        // add a new user operations  
    }  
}  

相关推荐

    单例模式.ppt

    【单例模式】是一种常用的软件设计模式,其主要目的是确保一个类只有一个实例,并提供一个...单例模式虽然方便,但过度使用可能导致设计复杂度增加,不易测试,以及违反了单一职责原则,因此在实际应用中应谨慎使用。

    C++中的单例模式及按需释放模型

    在描述中提到,传统的单例模式实现往往在程序运行结束时才会释放单例对象,即使在具有垃圾回收机制的语言如C#中也是如此。这种情况下,当系统切换到不使用特定单例对象的功能模块时,这些不再需要的单例仍然占用内存...

    2 单例模式-MOOC课程内容.pdf

    - 单例模式3使用了内部类来实现单例。SingletonHolder是一个私有的静态内部类,在Singleton类被加载时,SingletonHolder不会被加载,因此不会立即实例化Singleton。当getInstance()方法首次被调用时,...

    单例模式七种写法_转

    在软件工程领域中,单例模式是一种广泛使用的创建型设计模式,其目的是确保一个类只有一个实例,并提供一个全局访问点。单例模式在多线程环境下使用时,若不采取适当的同步措施,可能会导致创建多个实例,破坏模式的...

    JavaScript编程的单例设计模讲解

    不仅如此,单例模式在许多著名的JavaScript类库中也有应用,例如underscore和jQuery,可以说它们本身就是单例模式的一个实例。 通过单例模式,我们可以把相关的代码组织在一起,便于维护和重用。在大型项目中,通过...

    java设计模式之单例模式

    单例模式是java设计模式中的一种常用的创建型模式,是我们日常开发中最常使用的一种设计模式。它的主要作用是保证系统中一个类只有一个实例。单例模式可以被用来封装一些工具类,例如数据库连接等。 单例模式的定义...

    php单例模式的简单实现方法

    尽管如此,单例模式在PHP中的使用仍然有其特有的优势,比如减少new操作的资源消耗,便于调试和集中控制等。 具体到PHP实现单例的代码如下: ```php class Example { // 保存实例在此静态私有属性中 private ...

    Java多线程下的单例模式参考

    在Java编程中,单例模式是一种常见的设计模式,它保证一个类只有一个实例,并提供一个全局访问点。在多线程环境中,实现单例模式时需要特别注意线程安全问题,以防止在并发访问时产生多个实例。本篇将探讨如何在Java...

    PHP中数据库单例模式的实现代码分享

    尽管如此,单例模式在PHP中仍然有其用途,特别是在数据库操作和全局配置方面。 数据库单例模式在PHP中尤其重要,因为在Web应用中,数据库操作非常频繁。使用单例模式可以避免每次数据库操作时重复创建数据库连接,...

    鸡肋的PHP单例模式应用详解

    尽管如此,在实际应用中,特别是在涉及数据库操作的Web应用中,单例模式仍然具有其重要性。例如,在数据库操作中,可以使用单例模式来确保应用中只有一个数据库连接实例,这可以有效避免重复创建多个数据库连接所...

    js代码-js单例模式

    JavaScript中的单例模式是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。在软件工程中,单例模式被广泛应用,特别是在需要频繁实例化然后销毁的对象,或者创建对象需要消耗大量资源...

    通过示例分析Swift单例模式

    单例模式是软件设计模式中的一种,用于保证一个类只有一个实例,并提供一个全局访问点。在Swift编程语言中,有多种实现单例模式的方法。以下是根据标题和描述中提到的三种方式的详细解释: 1. **全局变量**: 在...

    java设计模式

    7.2 单例模式的定义 7.3 单例模式的应用 7.4 单例模式的扩展 7.5 最佳实践 第8章 工厂方法模式 8.1 女娲造人的故事 8.2 工厂方法模式的定义 8.3 工厂方法模式的应用 8.3.1 工厂方法模式的优点 8.3.2 工厂方法模式的...

    Java多线程编程环境中单例模式的实现

    单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点。在Java中,单例模式的应用非常广泛,特别是在资源管理、日志记录、数据库连接等方面。然而,在多线程环境中实现单例模式时,...

    【BAT必备】设计模式面试题

    - **解析**:单例模式是一种创建型设计模式,其目的是确保一个类只有一个实例,并提供一个全局访问点。这种模式常用于管理资源密集型的对象,如数据库连接、线程池等。通过确保此类对象在整个系统中只存在一个实例,...

    常用设计模式及Java程序 pdf

    设计模式如工厂模式可以帮助创建复杂对象实例,单例模式确保类只有一个实例存在。 - **管理对象间的交互**:例如观察者模式允许对象之间动态地定义一对多依赖关系,适配器模式则用于让不兼容的接口协同工作。 - **...

    Delphi设计模式

    本书可能并未涵盖所有设计模式,但即便如此,它依然提供了许多关键模式的解释和示例,如单例模式、工厂模式、观察者模式、装饰器模式、代理模式、建造者模式等。以下是对这些模式的详细描述: 1. **单例模式**:...

    P2P-chat:此 P2P 聊天已实现为群聊。 单例模式、观察者模式和 MVC 模式

    #P2P 聊天 此 P2P 聊天已实现为群聊。 聊天是这样实现的: 您必须首先在同一本地... 具体来说,这个项目使用了Singleton 、 Observer和MVC 模式。 ##技术Java ##Bibliography Head First 设计模式 - O'Reilly Media

Global site tag (gtag.js) - Google Analytics