23种设计模式
Posted 壹毫米的距离
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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!!!
以上是关于23种设计模式的主要内容,如果未能解决你的问题,请参考以下文章