1、单例模式
对于某个类只存在一个实例,并且该类只提供一个取得实例的方法(静态方法)。
实现单例模式的八种方法
- 饿汉式(静态常量)
初始化时会加载对象,没有使用对象,会造成内存的浪费,但避免了多线程的同步问题。
class Singleton{
//构造器私有化
private Singleton(){}
//类的内部创建对象 fianl static
private static final Singleton singleton = new Singleton();
//对外提供公共的静态方法,返回该类的唯一实例
public static Singleton getInstance(){
return singleton;
}
}
- 饿汉式(静态代码块)
初始化时会加载对象,没有使用对象,会造成内存的浪费,但避免了多线程的同步问题。
class Singleton{
//构造器私有化
private Singleton(){}
//类的内部创建对象
private static final Singleton singleton;
static {
singleton = new Singleton();
}
//对外提供公共的静态的方法
public static Singleton getInstance(){
return singleton;
}
}
- 懒汉式(线程不安全)
有懒加载的效果,不会造成内存的浪费,但线程不安全
class Singleton{
//构造器私有化
private Singleton(){}
//类的内部提供对象
private static Singleton singleton;
//对外提供公共的静态方法的时候,来判断
public static Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
- 懒汉式(线程安全,同步方法)
利用 synchronized 关键字来实现线程安全,但是效率较低。
class Singleton{
//构造器私有化
private Singleton(){}
//类的内部提供对象
private static Singleton singleton;
//对外提供公共的静态方法的时候,来判断
public static synchronized Singleton getInstance(){
if (singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
- 懒汉式(线程不安全,同步代码块)
该方法无任何意义,线程不安全(不推荐)
class Singleton{
//构造器私有化
private Singleton(){}
//类的内部提供对象
private static Singleton singleton;
//对外提供公共的静态方法的时候,来判断
public static Singleton getInstance(){
if (singleton == null){
synchronized (Singleton.class){
singleton = new Singleton();
}
}
return singleton;
}
}
- 双重检查(推荐使用)
该方法既起到了懒加载的效果,又解决了线程安全问题且效率较高。
class Singleton{
private Singleton(){}
//禁止指令重排
private static volatile Singleton singleton;
//加入双重检查机制
public static Singleton getInstance(){
if (singleton == null){
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 静态内部类(推荐)
利用静态内部类的方式实现模式,在类加载时静态内部类是不会装载的,只有用到了getInatance方法用到了静态变量的时候类才会被装载,利用了jvm的特性来实现了线程的安全。
class Singleton{
private Singleton(){}
private static class SingletonInstance{
public static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
- 枚举方法(推荐)
线程安全
enum Singleton{
INSTANCE; //属性
}
单例模式的使用场景
对于一些需要频繁创建和销毁的对象
重量级对象
工具类
经常使用到的对象
数据源,session。。。。
2、工厂模式
定义一个可以创建对象的类,由这个类来封装实例化对象的行为,在简单工厂模式中可以根据参数的不同返回不同的实例。
避免了业务逻辑和创造对象代码的大量耦合。
工厂方法模式:定义一个创建对象的抽象实例化方法,由子类来决定实例化哪些类。将对象实例化延迟到子类。
工厂方法模式是简单工厂模式的衍生,实现了可扩展,层次结构复杂,可以应用到更复杂的场景。
3、抽象工厂模式
定义一个接口,用于创建相关或有依赖关系的对象簇,而无需指明具体的类。
对象簇:一系列的对象。
4、原型模式
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象,既实现一个原型接口,该接口用于创建当前对象的克隆,当直接创建对象代价较大时使用这种模式。
利用object对象中的clone方法实现。
- 浅拷贝
对于数据类型时基本数据类型,浅拷贝就是值传递。
对于数据类型是应用型数据类型,浅拷贝就是引用传递(只是克隆之前的对象,不会创建新对象)。
- 深拷贝
复制对象的所有基本类型的成员变量值
为所有引用数据类型变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。
使用深拷贝会复制整个对象,包括引用型数据类型。
实现深拷贝的俩种方法 1、重写clone方法。2、对象序列化。
重写clone
public class DeepProtoType implements Cloneable{
public String name; //String类型
public DeepCloneableTarget deepCloneableTarget; //引用类型 ???
public DeepProtoType() {
super();
}
//完成深拷贝
//实现方式一:重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
//要拷贝的对象
Object deep = null;
//分布进行
//完成对于基本数据类型或者String类型的拷贝
deep = super.clone();
//对引用类型进行处理
DeepProtoType deepProtoType = (DeepProtoType) deep;
deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();
return deepProtoType;
}
}
该方法繁琐,需要得一个一个的对引用型数据类型进行处理。
对象序列化
一劳永逸,无需反复操作。
//完成深拷贝
//实现方式二:通过对象序列化的方式
public Object deepClone(){
//类需要实现序列化接口
//创建流对象
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
//序列化操作
try {
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this); //序列化
//反序列化操作
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
DeepProtoType deepProtoType = (DeepProtoType) ois.readObject();
return deepProtoType; //输出
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流对象
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
5、建造者模式
创建细节不要暴露,可以在内部创建。
创建者模式又叫生成器模式,是一种对象创建模式。
他可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现得对象。
建造者模式是一步一步创建一个复杂的对象,他允许用户只通过指定复杂对象的类型和内容就可以构建他们,用户不需要直到内部的构建细节
建造者模式的四个角色:
产品角色(product):一个具体的产品对象。
抽象建造者(builder):创建一个各个对象产品部件指定的一个接口或者是抽象类。
具体建造者(concreatebuilder):具体建造者,实现builder接口,构建和装配各个部件,来实现具体的细节。
指挥者(director):构建一个用来使用builder接口的对象,用来创建复杂的对象,主要有俩个作用。1、隔离了客户与对象的生产过程。2、负责控制产品的生产过程。
建造者模式适用于以下的几种场景:
1、相同的方法,不同的执行顺序,产生不用的结果时
2、多个部件或者零件,都可以装配到一个对象中,但是产生的结果又不相同
3、产品非常复杂,或者产品类中的调用顺序不用产生不同的作用
4、当时初始化一个对象特别复杂,参数多,而且很多参数都具有默认值时
若产品差异较大就不适合了。
抽象工厂模式,不需要关心创建的流程是怎样的,只需要关心用怎样的对象创建怎样的产品。
建造者模式,按照指定的蓝图构建产品,需要关注装配的顺序及过程。
stringbuilder就是使用了创建者模式
设计模式是一种思想。
不要为了使用而使用。