23种设计模式

一种设计模式:解决一种问题。

单例模式:

1、单例理解就是不能让外部去实例化对象,不能让外面随便new,外面可以随便new就表示不是单例的。

如何保证这个类不给外面的类实例化呢?

通常实例化一个对象,就是调用他的构造方法。只要把构造方法私有化后外部就不能调用构造方法去实例化对象。

 

2、声明一个本类对象

你不让外部去实例化一个对象,那么你自己实例化一个对象。

 

3、给外部提供一个静态公有方法获取对象实例

外部如何获取这个对象的实例呢?通过调用提供的这个静态方法,获取对象的实例。

=====================================================================

饿汉式:在多线程中不存在线程安全问题。

 1 /**
 2  *  单例:饿汉式
 3  * 
 4  * @author Administrator 
 5  * 
 6  * 1.私有的化构造方法
 7  * 2.指向自己实例的私有静态引用
 8  * 3.以自己实例为返回值的静态的公有的方法
 9  * 
10  * */
11 public class Singleton {
12 
13     private static Singleton singleton = new Singleton();
14 
15     private Singleton() {
16     }
17 
18     public static Singleton getInstance() {
19         return singleton;
20     }
21 }

 

懒汉式:在多线程中存在线程安全问题。

 1 /**
 2  *  单例:懒汉式,双层锁式
 3  * 
 4  * @author Administrator 
 5  * 
 6  * */
 7 public class Singleton {
 8 
 9     private static Singleton singleton = null;
10 
11     private Singleton() {
12     }
13 
14     public static Singleton getInstance() {
15         if (singleton == null) {
16             synchronized (Singleton.class) {
17                 if (singleton == null) {
18                     // -->0 -->1
19                     singleton = new Singleton();
20                 }
21             }
22         }
23         return singleton;
24     }
25 
26 }

 

解决在多线程中的安全问题,加同步锁。

加同步锁会导致效率问题,解决方式多加一个if语句进行判断。即双层锁式。

多线程:有0线程,1线程。

假如0线程获得执行权,挂到注释地方了,然后线程1进入,此时s==null,线程1也到了注释地方,接着线程0执行s= new Single()产生一个对象,返回s,

接着执行s= new Single();又产生一个对象,返回s;生成两个对象,所以线程不安全。

 

加synchronized代码块同步锁,保证只有一个线程进入该方法。

线程0,1,2.

线程0拿到锁,获得执行权,进入方法,s==null,线程0挂到注释地方了,其他线程锁判断,进不来线程0没释放锁,只能等线程0执行,new single(),返回s。

线程1锁判断,进入,s不等于null,直接返回上个s结果。

线程2锁判断,进入,s不等于null,直接返回上个s结果。解决线程安全问题。 

 

但是这样线程要进行锁判断,锁判断消耗资源,降低了效率。解决方式,即双层锁式。

 

线程0,1,2.

线程0进入,s==null,拿到锁,s==null,挂到注释地方。

线程1进入,s==null,拿不到锁,只能等线程0执行new single()并返回s释放锁,线程1拿到锁,进入s不等于null,直接返回s。

线程2进入,s不等于null,直接返回s。

 

=====================================================================

应用:jdbc连接数据库(单例模式)

ps:注意单例共用的是连接池,不是连接对象。

1、数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

2、多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。

 1 package com.sli;
 2  
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7 import java.sql.Statement;
 8  
 9 /**
10  * 
11  * @author yhmdjl JDBC辅助类 用于构建数据库连接(采用单例模式)
12  */
13 public final class JDBCUtilSingle {
14     // 该url为缺省方式(省略主机跟端口)
15     // 完整为:jdbc:mysql//localhost:3306/test
16     static String url = "jdbc:mysql:///test";
17     static String name = "root";
18     static String password = "sli";
19     static Connection conn = null;
20     private static JDBCUtilSingle jdbcUtilSingle = null;
21  
22     public static JDBCUtilSingle getInitJDBCUtil() {
23         if (jdbcUtilSingle == null) {
24             // 给类加锁 防止线程并发
25             synchronized (JDBCUtilSingle.class) {
26                 if (jdbcUtilSingle == null) {
27                     jdbcUtilSingle = new JDBCUtilSingle();
28                 }
29             }
30         }
31         return jdbcUtilSingle;
32     }
33  
34     private JDBCUtilSingle() {
35     }
36  
37     // 通过静态代码块注册数据库驱动,保证注册只执行一次
38     static {
39         try {
40             // 注册驱动有如下方式:
41             // 1.通过驱动管理器注册驱动,但会注册两次,并且会对类产生依赖。如果该类不存在那就报错了。
42             // DriverManager.registerDriver(new com.mysql.jdbc.Driver());
43             // 2.与3类似
44             // System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver");
45             Class.forName("com.mysql.jdbc.Driver");// 推荐使用方式
46         } catch (ClassNotFoundException e) {
47             e.printStackTrace();
48         }
49     }
50  
51     // 获得连接
52     public Connection getConnection() {
53         try {
54             conn = DriverManager.getConnection(url,name,password);
55         } catch (SQLException e) {
56             e.printStackTrace();
57         }
58         return conn;
59  
60     }
61  
62     // 关闭连接
63     public void closeConnection(ResultSet rs, Statement statement, Connection con) {
64         try {
65             if (rs != null) {
66                 rs.close();
67             }
68         } catch (SQLException e) {
69             e.printStackTrace();
70         } finally {
71             try {
72                 if (statement != null) {
73                     statement.close();
74                 }
75             } catch (Exception e) {
76                 e.printStackTrace();
77             } finally {
78                 try {
79                     if (con != null) {
80                         con.close();
81                     }
82                 } catch (SQLException e) {
83                     e.printStackTrace();
84                 }
85             }
86         }
87     }
88  

 

单例设计模式 END!!!

posted @ 2017-03-21 14:47  壹毫米的距离  阅读(175)  评论(0编辑  收藏  举报