单例模式与工厂方法模式
来源:互联网 发布:qq飞车b车 大黄蜂数据 编辑:程序博客网 时间:2024/05/16 12:01
http://blog.csdn.net/happy_horse/article/details/51164262
http://blog.csdn.net/beyond0525/article/details/22794221/
http://blog.csdn.net/liguangzhenghi/article/details/8076361
单例模式保证了在程序中只有一个实例存在并且能全局的访问到。(1.应用中某个实例对象需要频繁的被访问.2.应用中只允许存在一个实例)
实现单例模式有以下几个关键点:
(1)其构造函数不对外开放,一般为private;(构造函数私有化,使得客户端不能通过new的形式手动构造单例类的对象。)
(2)通过一个静态方法或者枚举返回单例类对象;(单例类的实例一旦创建,便不会被系统回收,除非手动设置为null。)
(3)确保单例类的对象有且只有一个,尤其要注意多线程的场景;
(4)确保单例类对象在反序列化时不会重新创建对象;
一、懒汉式(线程不安全)
//懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton {
//私有的构造函数
private Singleton() {}
//私有的静态变量
private static Singleton single=null;
//暴露的公有静态方法
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
(2)懒汉式(线程安全)使用synchronized 关键字
public class Singleton {
//私有的静态变量
private static Singleton instance;
//私有的构造方法
private Singleton (){};
//公有的同步静态方法
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
每次调用getInstance()都进行同步,造成了不必要的同步开销。这种模式一般不建议使用。在Android源码中使用的该单例方法有:InputMethodManager,AccessibilityManager等都是使用这种单例模式
(3)饿汉模式(线程安全)
//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton {
//static修饰的静态变量在内存中一旦创建,便永久存在
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
(4)DCL双重校验模式
public class Singleton {
private volatile static Singleton singleton; //静态变量
private Singleton (){} //私有构造函数
public static Singleton getInstance() {
if (singleton == null) { //第一层校验
synchronized (Singleton.class) {
if (singleton == null) { //第二层校验
singleton = new Singleton();
}
}
}
return singleton;
}
}
对singleton 进行了两次判断是否空,第一层判断是为了避免不必要的同步,第二层的判断是为了在null的情况下才创建实例。存在严重安全隐患。
(5)静态内部类单例模式
public class Singleton {
private Singleton (){} ;//私有的构造函数
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
//定义的静态内部类
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton(); //创建实例的地方
}
}
当第一次加载Singleton 类的时候并不会初始化INSTANCE ,只有第一次调用Singleton 的getInstance()方法时才会导致INSTANCE 被初始化。因此,第一次调用getInstance()方法会导致虚拟机加载SingletonHolder 类,这种方式不仅能够确保单例对象的唯一性,同时也延迟了单例的实例化。
使用:SingletonInner.getInstance();
(6)枚举单例
public enum Singleton { //enum枚举类
INSTANCE;
public void whateverMethod() {
}
}
(7)使用容器实现单例模式
public class SingletonManager {
private static Map<String, Object> objMap = new HashMap<String,Object>();//使用HashMap作为缓存容器
private Singleton() {
}
public static void registerService(String key, Objectinstance) {
if (!objMap.containsKey(key) ) {
objMap.put(key, instance) ;//第一次是存入Map
}
}
public static ObjectgetService(String key) {
return objMap.get(key) ;//返回与key相对应的对象
}
}
在程序的初始,将多种单例模式注入到一个统一的管理类中,在使用时根据key获取对应类型的对象。
在Android源码中,APP启动的时候,虚拟机第一次加载该类时会注册各种ServiceFetcher,比如LayoutInflater Service。将这些服务以键值对的形式存储在一个HashMap中,用户使用时只需要根据key来获取到对应的ServiceFetcher,然后通过ServiceFetcher对象的getService函数获取具体的服务对象。当第一次获取时,会调用ServiceFetcher的creatService函数创建服务对象,然后将该对象缓存到一个列表中,下次再取时直接从缓存中获取,避免重复创建对象,从而达到单例的效果。Android中的系统核心服务以单例形式存在,减少了资源消耗。
总结:不管以哪种形式实现单例模式,它们的核心原理是将构造函数私有化,并且通过静态公有方法获取一个唯一的实例,在这个获取的过程中必须保证线程的安全,同时也要防止反序列化导致重新生成实例对象。
工厂方法模式
http://blog.csdn.net/self_study/article/details/51419770
任何需要生成复杂对象的地方,都可以使用工厂方法模式。工厂方法模式(Factory Method Pattern)定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类,这样的设计将对象的创建封装其来,以便于得到更松耦合,更有弹性的设计。降低了对象之间的耦合度,代码结构清晰,对调用者隐藏了产品的生产过程,生产过程改变后,调用者不用做什么改变,易于修改。易于拓展,要增加工厂和产品都非常方便,直接实现接口,不用修改之前的代码。
Product(抽象产品角色):它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
ConcreteProduct(具体产品角色):具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
Factory(抽象工厂角色):这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
ConcreteFactory(具体工厂角色):它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
模式1
1.抽象的产品:
public abstract class Product {
public abstract void method();
}
2.具体的产品:
public class ConcreteProductA extends Product {
@Override
public void method() {
System.out.println("产品A");
}
}
public class ConcreteProductB extends Product {
@Override
public void method() {
System.out.println("产品B");
}
}
3.抽象的工厂:
public abstract class Factory {
public abstract Product createProduct();
}
4.具体的工厂:
public class ConcreteFactory extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
5.客户端使用:
public class Client {
public static void main(String[] args) {
Factory factory = new ConcreteFactory();
Product product = factory.createProduct();
product.method();
}
}
这样就生产出来一个ConcreteProductA。
模式2
通过反射来了解要生产哪个产品
1.抽象工厂:
public abstract class Factory {
public abstract <T extends Product> T createProduct(Class<T> clz);
}
2.具体工厂:
public class ConcreteFactory extends Factory {
@Override
public <T extends Product> T createProduct(Class<T> clz) {
Product product = null;
try {
product= (Product) Class.forName(clz.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return (T) product;
}
}
3.客户端调用:
public class Client {
public static void main(String[] args) {
Factory factory = new ConcreteFactory();
Product product = factory.createProduct(ConcreteProductB.class);
product.method();
}
}
这样,客户端调用的时候,传入什么产品就生产什么产品。
模式3
可以为每个产品都创建一个具体的工厂类,如:
public class ConcreteFactoryA extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
public class ConcreteFactoryB extends Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
要生产哪个就调用哪个工厂。这种叫多工厂方法模式。
- 单例模式与工厂方法模式
- 简单工厂模式 单例工厂模式 工厂方法模式 抽象工厂模式 原型模式
- 单例模式/工厂方法模式/抽象工厂模式
- 工厂方法模式、抽象工厂模式、单例模式
- 单例模式与工厂模式
- 单例模式与工厂模式
- PHP单例模式与工厂模式
- PHP (单例模式与工厂模式)
- 工厂模式与单例模式笔记
- 单例模式、工厂模式、抽象模式、模板方法模式
- 单例模式与单例工厂
- 设计模式之简单工厂模式与单例模式
- 设计模式之单例模式与工厂模式
- 工厂模式-单例模式
- 单例模式、工厂模式
- 工厂模式、单例模式
- 单例模式/工厂模式
- 工厂模式&&单例模式
- SVN
- 归并排序
- MongoDB安装到windows服务的方法及遇到问题的完美解决方案
- spring-cloud【Hystrix】
- GPIO基础知识
- 单例模式与工厂方法模式
- 游戏人生
- 白话C++系列(const再现江湖)
- 数据结构实验之排序一:一趟快排
- java网络图片抓取及其引发的相关问题
- springboot框架用户信息的增删改
- Android RecyclerView的使用(三)——瀑布流的实现
- Unity3D
- poi导出EXCEL经典实现()