创建者模式:创建者模式主要的关注点事怎样创建对象,他的主要特点是“将对象的创建和使用分离”,这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。
创建者模式分为:
单例模式(Singleton Pattern)是java中最简单的设计模式之一。这种类型的设计模式属于一种创建类模式,它属于一种创建对象的最佳模式。
这种设计模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建,这个类提供了唯一一种访问其对象的方法,可以直接访问,不需要实例化该类的对象。
单例模式的主要角色如下:
实现模式分为两种:
懒汉式:类加载的时候会导致该单例模式被创建
饿汉式:类加载不会导致该单例模式的对象被创建,而是首次使用该对象的时候被创建
1、饿汉式-方式1(静态变量方式)
package creatorPattren.singleton.demo01;
/**
* 第一种饿汉式 实现单例模式
*
* 使用静态成员变量的方式创建类
* 向外提供一个公开的获得类的方法
*/
public class Singleton01 {
//私有化类的构造方法
private Singleton01() { }
private static Singleton01 intance = new Singleton01();
public static Singleton01 getIntance() {
return intance;
}
}
2、饿汉式-方式2(加锁静态变量方式)
package creatorPattren.singleton.demo02;
/**
* 第二种饿汉式 实现单例模式
*
* 使用静态成员变量的方式创建类
* 向外提供一个公开的获得类的方法
*/
public class Singleton02 {
//私有化类的构造方法
private Singleton02() { }
private static Singleton02 intance;
public static Singleton02 getIntance() {
//在这里才将类赋值
if (intance == null) {
intance = new Singleton02();
}
return intance;
}
}
3、饿汉式-方式3(使用内部类方式)
package creatorPattren.singleton.demo05;
/**
* 第三种饿汉式 实现单例模式
* 使用内部类的方式实现
* 使用静态成员变量的方式创建类
* 向外提供一个公开的获得类的方法
*/
public class Singleton05 {
//私有化类的构造方法
private Singleton05() { }
private static class getSingleton{
private static final Singleton05 INSTANCE= new Singleton05();
}
public static Singleton05 getIntance() {
return getSingleton.INSTANCE;
}
}
4、饿汉式-方式4(使用静态代码块方式)
package creatorPattren.singleton.demo06;
/**
* 第四种饿汉式 实现单例模式
* 使用静态代码块的方式实现
* 使用静态成员变量的方式创建类
* 向外提供一个公开的获得类的方法
*/
public class Singleton06 {
//私有化类的构造方法
private Singleton06() { }
private static Singleton06 instance;
static {
instance = new Singleton06();
}
public static Singleton06 getIntance() {
return instance;
}
}
5、饿汉式-方式5(使用枚举类型方式)
package creatorPattren.singleton.demo07;
/**
* 使用枚举类型
*/
public enum Singleton07 {
INTANCE
}
1、懒汉式-方式1(单个锁)
package creatorPattren.singleton.demo03;
/**
* 第一种懒汉式 实现单例模式
* 在第二种的基础上添加了synchronized关键字,解决了保证了多线程情况下依旧可以实现单例模式
* 使用静态成员变量的方式创建类
* 向外提供一个公开的获得类的方法
*/
public class Singleton03 {
//私有化类的构造方法
private Singleton03() { }
private static Singleton03 intance;
public static synchronized Singleton03 getIntance() {
//在这里才将类赋值
if (intance == null) {
intance = new Singleton03();
}
return intance;
}
}
2、懒汉式-方式2(双重锁)
package creatorPattren.singleton.demo04;
/**
* 第二种懒汉式 实现单例模式
* 在第三种的基础上改进了锁的机制,改为了双层锁,一定程度上减少了内存的消耗
* 使用静态成员变量的方式创建类
* 向外提供一个公开的获得类的方法
*/
public class Singleton04 {
//私有化类的构造方法
private Singleton04() { }
private static Singleton04 intance;
public static Singleton04 getIntance() {
//第一次判断
if (intance == null) {
synchronized (Singleton04.class){
// 第二次判断
if (intance == null) {
intance = new Singleton04();
}
}
}
return intance;
}
}
可以使用序列化和反射的方式破坏单例模式
序列化的方式:
package creatorPattren.singleton.demo08;
import java.io.*;
/**
* 使用序列化的方式破坏单例模式(枚举类型除外)
*/
public class BreakSingleton {
public static void main(String[] args) throws Exception {
// outFileToUSB();
getFileFromUSB();
getFileFromUSB();
}
public static void outFileToUSB() throws Exception {
//创建输出流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\a\\b.txt"));
//获得对象
Singleton08 intance = Singleton08.getIntance();
oos.writeObject(intance);
System.out.println("执行成功");
}
public static void getFileFromUSB() throws Exception {
//获得输入流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\a\\b.txt"));
Singleton08 intance = (Singleton08) ois.readObject();
System.out.println(intance);
}
}
反射的方式
package creatorPattren.singleton.demo08;
import creatorPattren.singleton.demo05.Singleton05;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* 使用反射破坏单例模式
*/
public class BreakSingleton02 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1、获得Singleton05的字节码文件
Class clazz = Singleton05.class;
//2获得无参构造方法对象
Constructor constructor = clazz.getDeclaredConstructor();
//3、取消访问检查
constructor.setAccessible(true);
//4、创建对象
Singleton05 instance = (Singleton05) constructor.newInstance();
Singleton05 instance1 = (Singleton05) constructor.newInstance();
System.out.println(instance == instance1);
}
}
使用resdResolve方法解决序列化出现的问题,在单例模式的类中加入此代码,返回值为单例模式的类。作用是在反射的时候返回同一个值,而不是新new出来一个
public Object readResolve(){
return instance;
}
package creatorPattren.singleton.demo08;
import java.io.Serializable;
/**
* 第四种饿汉式 实现单例模式
* 使用静态代码块的方式实现
* 使用静态成员变量的方式创建类
* 向外提供一个公开的获得类的方法
*/
public class Singleton08 implements Serializable {
//私有化类的构造方法
private Singleton08() { }
private static Singleton08 instance;
static {
instance = new Singleton08();
}
public Object readResolve(){
return instance;
}
public static Singleton08 getIntance() {
return instance;
}
}
解决反射问题
package creatorPattren.singleton.demo05;
/**
* 第三种饿汉式 实现单例模式
* 使用内部类的方式实现
* 使用静态成员变量的方式创建类
* 向外提供一个公开的获得类的方法
*/
public class Singleton05 {
private static boolean flag = false;
//私有化类的构造方法
private Singleton05() {
synchronized (Singleton05.class){
// 解决反射下的破坏单例模式的代码
if (flag) {
throw new RuntimeException("不能创建多个对象");
}
flag = true;
}
}
private static class getSingleton{
private static final Singleton05 INSTANCE= new Singleton05();
}
public static Singleton05 getIntance() {
return getSingleton.INSTANCE;
}
}