单例
因为单例迟早是要实例化的,延迟懒加载的加锁反而会造成资源浪费,同步问题会降低CPU利用率,因此一般采用饿汉模式。
饿汉模式
在类加载时就初始化对象,之后一直返回这个对象。
public class Sun {/*** static确保在类加载时初始化,在内存中永存,不会被GC回收;final确保是常量,引用一旦被赋值就无法更改*/private static final Sun sun = new Sun();/*** 私有构造,封闭太阳类使得外部类无法干预内部的实例化*/private Sun() {}/*** 由于构造私有,static是为了保证能调用此方法*/public static Sun getInstance() {return sun;}}
懒汉模式
第一次需要时创建对象,之后一直使用这个对象,不再重复创建。
public class Sun {/*** 保证各线程副本数据与公共内存中保持一致*/private volatile static Sun sun;private Sun() {}public static Sun getInstance() {// 此处加个判断是为了在已赋值情况下直接返回对象,无需让线程再等待if (sun == null) {// 加锁,让多线程排队等待synchronized (Sun.class) {// 此处是为了保证轮到其他线程后,防止太阳对象再次被赋值if (sun == null) {sun = new Sun();}}}return sun;}}
public class Main {public static void main(String[] args) {Sun eagerSun01 = Sun.getInstance();Sun eagerSun02 = Sun.getInstance();D01Singleton.lazy.Sun lazySun01 = D01Singleton.lazy.Sun.getInstance();D01Singleton.lazy.Sun lazySun02 = D01Singleton.lazy.Sun.getInstance();System.out.println(eagerSun01 == eagerSun02); //trueSystem.out.println(lazySun01 == lazySun02); //true}}
原型
从原型实例克隆创建对象,而不是用类创建对象。对于有非常复杂的初始化过程的对象或者是需要耗费大量资源时,可采用原型模式。
实现原型模式的关键在于拷贝(克隆),拷贝分为浅拷贝和深拷贝,因此原型模式拷贝也有两种,想要实现什么样的原型模式视情况决定。
浅拷贝、深拷贝
Java中的变量分为原始类型和引用类型,浅拷贝是值拷贝,它会复制原始类型的值和引用类型的地址引用,因此复制后的引用类型对象和被复制的引用类型对象会是同一对象。Java中的父类Object的clone方法就是浅拷贝。
深拷贝就是在浅拷贝的基础上,将引用类型完全复制一份,复制前后的两个对象不是同一地址引用。
Java实现
Java中的实现通过实现cloneable接口即可实现原型模式。
浅拷贝
public class Bullet implements Cloneable {private int speed;public Bullet(int speed) {this.speed = speed;}public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}/*** 需要注意返回是Bullet对象,默认重写方法是Object*/@Overrideprotected Bullet clone() throws CloneNotSupportedException {return (Bullet) super.clone();}}
public class EnemyPlaneShallow implements Cloneable {private int x;private int y = 0;private Bullet bullet;public EnemyPlaneShallow(int x, Bullet bullet) {this.x = x;this.bullet = bullet;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void fly() {y++;}public Bullet getBullet() {return bullet;}public void setBullet(Bullet bullet) {this.bullet = bullet;}@Overrideprotected EnemyPlaneShallow clone() throws CloneNotSupportedException {return (EnemyPlaneShallow) super.clone();}}
深拷贝
public class EnemyPlaneDeep implements Cloneable {private int x;private int y = 0;private Bullet bullet;public EnemyPlaneDeep(int x, Bullet bullet) {this.x = x;this.bullet = bullet;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void fly() {y++;}public Bullet getBullet() {return bullet;}public void setBullet(Bullet bullet) {this.bullet = bullet;}@Overrideprotected EnemyPlaneDeep clone() throws CloneNotSupportedException {EnemyPlaneDeep plane = (EnemyPlaneDeep) super.clone();plane.setBullet(this.bullet.clone()); // 对引用类型单独进行深拷贝return plane;}}
测试
public class Main {public static void main(String[] args) throws CloneNotSupportedException {EnemyPlaneShallow planeShallow = new EnemyPlaneShallow(10, new Bullet(11));EnemyPlaneShallow planeShallowClone = planeShallow.clone();System.out.println(planeShallow.getBullet() == planeShallowClone.getBullet()); // trueEnemyPlaneDeep planeDeep = new EnemyPlaneDeep(10, new Bullet(11));EnemyPlaneDeep planeDeepClone = planeDeep.clone();System.out.println(planeDeep.getBullet() == planeDeepClone.getBullet()); // false}}
