一、单例模式
单例模式一共有8种,除了常见的饿汉式,懒汉式,还有双重检查(实际开发中推荐使用),静态内部类
1、双重检查 voliated和 synchronized 的组合使用(推荐使用)
volatile:多个线程拿到一个共享变量,如果一个线程改变了共享变量里面的值,则其他的线程的共享变量的值也发生改变
例子:
package voliteaed;
/**
* <简述>
* <详细描述>
*
* @author LiuShanshan
* @version $Id$
*/
public class Singleton {
private static volatile Singleton singleton;
private Singleton(){
}
public static Singleton getInstance(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
线程安全;延迟加载;效率较高
2、静态内部类(推荐使用,jvm帮我们控制线程安全)
package voliteaed;
/** 静态内部类
* <简述>
* <详细描述>
*
* @author LiuShanshan
* @version $Id$
*/
public class StaticSingleton {
public static void main(String[] args) {
SingletonDemo1 instance = SingletonDemo1.getInstance();
SingletonDemo1 instance2 = SingletonDemo1.getInstance();
System.out.println(instance == instance2);
}
}
// 使用静态内部类生成对象
class SingletonDemo1{
private SingletonDemo1(){
}
private static class singletonDemo2{
private final static SingletonDemo1 singletoDemo1 = new SingletonDemo1();
}
public static SingletonDemo1 getInstance(){
return singletonDemo2.singletoDemo1;
}
}
避免了线程不安全,利用静态内部类特点实现延迟加载,效率高
3、枚举(推荐使用)
例子:
package voliteaed;
/** 枚举的方式实现单例
* <简述>
* <详细描述>
*
* @author LiuShanshan
* @version $Id$
*/
public class EnumDmo1 {
public static void main(String[] args) {
Demo1 sfsd = Demo1.SFSD;
Demo1 sfsd1 = Demo1.SFSD;
System.out.println(sfsd == sfsd1);
sfsd.get();
}
}
enum Demo1{
SFSD;
public void get(){
System.out.println("枚举方式使用单例");
}
}
- 这借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
- 这种方式是Effective Java作者Josh Bloch 提倡的方式
jdk源码中体现
在RunTime中体现了饿汉式
二、工厂模式
1、简单工厂模式
简单工厂模式的核心相当于在 7种设计方式最上面图的提供者那边又新增了一个类(工厂类),提供者可以新增类,新增的类处理业务,使用者不变,所以如果后面增加的提供者,也只需要更改工厂类代码,而不是动使用者代码
如图所示:
2、工厂方法模式
工厂方法模式的运用为写几个类(工厂方法)继承使用方(使用方为抽象类),调用方使用的时候,创建工厂方法对象即可。
3、抽象工厂模式
1、创建抽象类或者接口,继承他们或者实现他们的叫做抽象工厂类,使用方里面聚合抽象类(作为属性注入进去),然后调用方调用使用方,传入对应的工厂类对象即可
4、观察者模式
参考博客:https://blog.csdn.net/CSDN2497242041/article/details/120403205
java中Observable是抽象目标类(被观察的类),Observer是接口,继承了这个类就代表类为观察者。
Observable 类是抽象目标类,它有一个 Vector 向量,用于保存所有要通知的观察者对象,下面来介绍它最重要的 3 个方法。
- void addObserver(Observer o) 方法:用于将新的观察者对象添加到向量中。
- void notifyObservers(Object arg) 方法:调用向量中的所有观察者对象的 update()
方法,通知它们数据发生改变。通常越晚加入向量的观察者越先得到通知。 - void setChange() 方法:用来设置一个 boolean类型的内部标志位,注明目标对象发生了变化。当它为真时,notifyObservers() 才会通知观察者。
三、原型模式(克隆模式)
注意点:需要克隆的类,需要实现 cloneable接口,不然报错java.lang.CloneNotSupportedException
例子:
1、浅拷贝
package 原型模式;
/**
* <简述>
* <详细描述>
*
* @author LiuShanshan
* @version $Id$
*/
public class Yuanxing implements Cloneable{
private String name;
private String age;
public Yuanxing(String name, String age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Yuanxing{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
// 拷贝当前对象
Yuanxing clone = null;
try {
clone = (Yuanxing)super.clone();
} catch (Exception e){
e.printStackTrace();
}
return clone;
}
}
2、深拷贝(推荐使用序列化的方式)
例如:
package 原型模式;
import jdk.jfr.events.ExceptionThrownEvent;
import java.io.*;
/**
* <简述>
* <详细描述>
*
* @author LiuShanshan
* @version $Id$
*/
public class Yuanxing implements Serializable,Cloneable{
private String name;
private String age;
private YuanxingObject yuanxingObject;
public Yuanxing(){
super();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public YuanxingObject getYuanxingObject() {
return yuanxingObject;
}
public void setYuanxingObject(YuanxingObject yuanxingObject) {
this.yuanxingObject = yuanxingObject;
}
@Override
public String toString() {
return "Yuanxing{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
// 拷贝当前对象
Yuanxing clone = null;
clone = (Yuanxing)super.clone();
if(yuanxingObject != null){
clone.setYuanxingObject((YuanxingObject)yuanxingObject.clone());
}
return clone;
}
/**
*<简述> 深clone
*<详细描述>
* @author Liushanshan
* @param
* @return 原型模式.Yuanxing
*/
public Yuanxing cloneDeep() throws IOException, ClassNotFoundException {
ObjectOutputStream oos;
ByteArrayOutputStream bos;
ObjectInputStream ois;
ByteArrayInputStream bis;
try {
// 序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this); // 放入当前对象
oos.flush();
// 反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
Yuanxing yuanxing = (Yuanxing)ois.readObject();
return yuanxing;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
总结
缺点:需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了ocp原则,这点请同学们注意.