1.单例模型
有时候在我的设计中,所有的类只共享一个实例,那么这时候就需要设计一个单实例的类。
思路是将这个类构造器私有化,这样外部就无法直接创建对象,然后提供公有的静态方法,让外部去调用。具体的实现方式有四种方式
方式一:饿汉模式
public class Singleton {
// 创建本类的私有构造方法
private Singleton(){}
private static Singleton singleton = new Singleton();
public static Singleton getInstance(){
return singleton;
}
}
饿汉模式在类加载是就已经创建了类对象,不管是否使用该类的实例,它已经在堆内存里。
直接将该类的实例对象作为属性实现的
方式二:懒汉模式
public static LazySingleton getInstance(){
if(singleton == null){
synchronized (LazySingleton.class){
if(singleton == null){
singleton = new LazySingleton();
}
}
}
return singleton;
}
之所以成为懒汉模式,是相对于饿汉模式说,因为饿汉模式是你不管是不是使用这个类,都会产生这个类的实例,而懒汉模式是在getInstance()这个方法里面new出来的,所以只有调用这个方法,才会在堆内存种产生类实例。
通过双重检测 和 同步代码块synchronized{} 使得代码执行的高效和线程安全
方式三:通过枚举
public class EnumSingleton {
private EnumSingleton(){}
private static enum SinEnum{
// 自定义的枚举值 如果没有该自定义枚举值 无法获取枚举对象
TEST;
private EnumSingleton es = new EnumSingleton();
}
public static EnumSingleton getInstance(){
SinEnum sinEnum = SinEnum.TEST;
return sinEnum.es;
}
}
方式四:匿名内部内
/**
* 通过静态内部类 完成单例模式的创建
* 在外部类加载时,并不会加载内部类,也就是不会执行new 实例(),这属于懒加载
* 只有第一次调用getInstance方法时,才会加载
*/
public class InnerSingleton {
private InnerSingleton(){}
// 静态内部类
private static class Inner{
private static InnerSingleton instance = new InnerSingleton();
}
public static InnerSingleton getInstance(){
return Inner.instance;
}
}
2.代理模式
把核心的业务抽象成一个接口,然后让被代理者抽象成一类去实现这个接口,代理者也抽象成一个类去实现这个接口,然后将被代理者类实例在代理者类中设计成为它的一个属性,然后代理者类就可以在实现的方法中,使用被代理的核心业务方法,同时可以加上一些非核心的业务。
请想像这样一个场景:你是一个租客,你需要租房子,那么你回去找房产中介帮你完成你的需求(租房子),
所以可以将租房子业务抽象成一个接口
public interface RentRoom {
//核心业务:租房子
public void rent();
}
租客类去实现这个接口
//租客
public class Renter implements RentRoom{
public void rent() {
System.out.println("租房子");
}
}
中介类中也去实现租房的业务接口,把租客类实例作为自己的属性,因此可以直接使用租客类的核心业务方法,同时也可以加上一些非核心的业务逻辑,这样就可以让中介类完成租房子的业务。也就是通过调用中介类实例的renter方法
//房产中介
public class Agency implements RentRoom {
private Renter renter = new Renter();
public void rent() {
System.out.println("找房子");//这个是非核心业务,中介干的活
renter.rent(); //这个是核心业务
}
}