单例模式伪应用举例与其存在的意义

来源:互联网 发布:矩阵svd分解 例子 编辑:程序博客网 时间:2024/05/21 08:40
参考文献
单例模式VS静态方法 :http://www.cnblogs.com/seesea125/archive/2012/04/05/2433463.html
单例模式解说:  http://blog.csdn.net/guolin_blog/article/details/8860649
向原博主致敬!本文的出现主要基于以上两篇博客。为什么说是“单例模式伪应用举例”呢?实际生产环境是不会用实验中方法打印日志与获取数据库连接的,只是单例模式学习用。
场景

阅读完郭霖的单例模式解说,感觉那个小日志工具写的不错,这里自己再写一下,随便把以前学单例模式时写的数据库连接整到一起来复习。

问题来了:为什么使用单例模式而不是静态方法呢?单例模式就比静态方法好吗?

这关乎单例模式存在的意义:你挖空心思整一个单例模式出来,好像很有技巧的样子,可完全没有必要啊?单例能干的事情,静态方法都可以实现。

个人认为单例模式vs静态方法的讨论,实际上 是静态方法 与 非静态方法(实例方法)的讨论。比较赞同以下言论:

早期的结构化编程,几乎所有的方法都是“静态方法”,引入实例化方法概念是面向对象概念出现以后的事情了,区分静态方法和实例化方法不能单单从性能上去理解,创建c++,java,c#这样面向对象语言的大师引入实例化方法一定不是要解决什么性能、内存的问题,而是为了让开发更加模式化、面向对象化。这样说的话,静态方法和实例化方式的区分是为了解决模式的问题。

虽然都能实现目的,但是他们一个是基于对象,一个是面向对象的,就像我们不面相对象也能解决问题一样,面相对象的代码提供一个更好的编程思想。

也就是说,单例模式更加面向对象。现存的就是合理的,以后遇到这种类型的问题,也可以从应用历史发展的角度考虑,把注意力放到 每种方式实现的优点上来。

实验
单例实现日志工具 与获取数据库连接

package design;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.util.Properties;/** * 单例模式 * 定义:用单个的实例去有效地解决一类应用问题 *  * 使用方法: * 1、定义一个该类的静态成员变量,并指向该类的唯一实例。 * 2、私有化构造方法 3、定义一个静态方法返回该类唯一的实例 *  * 伪应用举例:1、数据库连接  2、生产坏境日志的打印 *  * @date 2016/3/18 10:30 * @author Mr.Snail * */public class Singleton{public static void main(String[] args){LogUtil.getInstance().info("test singleton design modern ");System.out.println(ConnectionManager.getInstance().getConnection());}}/** * 单例模式应用 之 日志工具 * 场景分析:为了定位问题方便,每个类中都需要打印。如果每次打印日志(这里以debug级别为例) * 都  new Log().debug(),也就是记录一次日志 new 一个Log对象,显然浪费内存空间。这种情况就可以 * 使用单例模式来解决。 *  * 说明:生成LogUtil类的单例时 方法二比方法一更优雅,使用方法一只是为了学习一下 传说中的 双重锁定(Double-Check Locking) * @author Administrator * */class LogUtil{private static int debug = 0;private static int info = 1;private static int error = 2;private static int level = debug;//在配置文件中,值可配置private LogUtil(){}private static LogUtil logUtil = null; //方法一public static LogUtil getInstance(){
<span style="white-space:pre"></span>// 双重锁定if(null == logUtil){synchronized (LogUtil.class){if(null == logUtil){logUtil = new LogUtil();}}}return logUtil;}//private static final LogUtil logUtil = new LogUtil(); 方法二//public static LogUtil getInstance(){return logUtil} public void debug(String message){if(debug>=level){System.out.println(message);}}public void info(String message){if(info>=level){System.out.println(message);}}public void error(String message){if(error>=level){System.out.println(message);}}}/** * 单例模式应用 之 获取数据库连接 * @author Mr.Snail * */class ConnectionManager{private static final String USERNAME = "root";private static final String PASSWORD = "1989321_ivy";private static final String DRIVER = "com.mysql.jdbc.Driver";private static final String URL = "jdbc:mysql://112.74.21.122:3306/mysql";//当然一般情况,以上参数都是读取配置文件,或者是依赖注入进来的,这里以读取配件文件为例,随便复习一下//Properties类的操作方法Properties properties = new Properties();private static final ConnectionManager cManager = new ConnectionManager();private ConnectionManager(){//InputStream is = this.getClass().getResourceAsStream("./db.properties");//try//{//properties.load(is);//USERNAME = properties.getProperty("username");//PASSWORD = properties.getProperty("password");//DRIVER = properties.getProperty("driver");//URL = properties.getProperty("url");//}//catch (IOException e)//{//LogUtil.getInstance().error(e.toString());//}}public static ConnectionManager getInstance(){return cManager;}/** * 获取数据库连接 * @return Connection */public Connection getConnection(){Connection conn = null;try{Class.forName(DRIVER);conn =  DriverManager.getConnection(URL, USERNAME, PASSWORD);} catch (ClassNotFoundException e){LogUtil.getInstance().error(e.toString());throw new RuntimeException(e.toString());}catch (SQLException e){LogUtil.getInstance().error(e.toString());throw new RuntimeException(e.toString());}return conn;}}
0 0
原创粉丝点击