1. 为什么需要学习设计模式
设计模式(Design pattern)代表了最佳的实践,是很多优秀的软件开发人员的经验总结,是解决特定问题的解决方案。它并不是语法规定,也不拘泥于特定语言。 恰当的使用设计模式可以代码的可复用性,可维护性,可扩展性,健壮性及安全性,这些都是系统非常重要的非功能性需求。
设计模式的广泛使用起始于1995年,GOF(四人帮)出版的《设计模式:可复用面向对象软件基础》。
2. 常见的设计模式
2.1:单例模式
优点:
- 在内存中只有一个对象,节省内存空间;
- 避免频繁的创建销毁对象,可以提高性能;
- 避免对共享资源的多重占用,简化访问;
- 为整个系统提供一个全局访问点。
缺点:
- 不适用于变化频繁的对象;
- 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;
示例:
1.单例模式:饥饿加载
package com.DanLiDemo; /** * 饥饿加载。 */ public class JiEdemo { //构造方法私有化;防止其它类调用创建实例。 private JiEdemo(){}; //进来默认创建一个实例; private static final JiEdemo je=new JiEdemo(); //获取默认实例 public static JiEdemo getSl(){ return je; } public static String getHello(String s){ return "Hello "+s; } /* * 测试多线程下单例模式是否安全 * @param args */ public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(()->{ System.out.println(JiEdemo.getSl().hashCode()); }).start(); } } }
2.单例模式:懒汉式,锁旗标,效率较低。
package com.DanLiDemo; /** * 单例模式: 懒汉式, 锁旗标有点降低效率。 */ public class JiEdemo02 { private JiEdemo02(){//InterruptedException try{ Thread.sleep(10); }catch(InterruptedException e){ e.printStackTrace(); }; }; private static JiEdemo02 je=null; public synchronized static JiEdemo02 getSl(){ if(je==null){ je=new JiEdemo02(); } return je; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(()->{ System.out.println(JiEdemo02.getSl().hashCode()); }).start(); } } }
3.单例模式:懒汉式,双重检查,效率较高。
package com.DanLiDemo; /** * 单例模式: 懒汉式,线程安全,双重检查单例,效率较高 */ public class JiEdemo03 { private JiEdemo03(){ try{ Thread.sleep(20); }catch(InterruptedException e){ e.printStackTrace(); } } private static JiEdemo03 je3=null; public static JiEdemo03 getSl(){ if(je3==null){ synchronized (JiEdemo03.class){ if(je3==null) { je3 = new JiEdemo03(); } } } return je3; } public static void main(String[] args) { for (int i = 0; i <100 ; i++) { new Thread(()->{ System.out.println(JiEdemo03.getSl().hashCode()); }).start(); } } }
4.懒汉式:静态内部类
package com.DanLiDemo; /** * 单例模式: 懒加载, 线程安全,静态内部类 */ public class JiEdemo04 { private JiEdemo04(){ try { Thread.sleep(10); }catch (InterruptedException e){ e.printStackTrace(); } }; public static final class JiEdemo0401{ private static final JiEdemo04 je4=new JiEdemo04(); } public static JiEdemo04 getSl(){ return JiEdemo0401.je4; } public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(()->{ System.out.println(JiEdemo04.getSl().hashCode()); }).start(); } } }
5.单例模式:枚举
package com.DanLiDemo; /** * 单例模式:枚举 */ public enum JiEdemo05 { je; public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(()->{ System.out.println(JiEdemo05.je.hashCode()); }).start(); } } }
2.2:工厂模式
2.2.1 概念
用于产生对象的方法或者式类,称之为工厂。 上面所讲到的单例模式也可以看作为一个特殊的工厂。
2.2.2 使用场景
为什么需要工作模式,原来使用new的方式感觉也很简单,且好懂?
使用工厂的原因是我们可以通过工厂模式,来集中控制对象的创建过程,这样可以给设计带来更多的灵活性。
比如:spring的IOC容器就是工厂模式的经典实现。
2.2.3 工厂方法
用于生产指定系列的对象。已鸭子为例,鸭子有真的鸭子,橡皮鸭,电子玩具鸭等。如何能方便的创建出各种鸭子,并将创建过程控制起来,以便于以后的维护和扩展?
类图: