单例模式:

为什么使用单例: 节省内存资源, 保证数据的一致性。此外很多时候整个系统只需要拥有一个全局对象,有利于我们协调系统整体的行为。

代码模拟:

  1. /**
  2. * 饿汉式: 在加载类时候创建类的实例,并保存在类中
  3. * 线程安全 但浪费资源
  4. */
  5. public class HungrySingleton {
  6. private HungrySingleton() {}
  7. private static final HungrySingleton instance = new HungrySingleton();
  8. public static HungrySingleton getInstance() {
  9. return instance;
  10. }
  11. }
  12. ===============
  13. /**
  14. * 懒汉式: 不在系统加载时创建类的单例, 而是第一次使用实例时候创建。
  15. */
  16. public class LazySingleton {
  17. /**
  18. * 保证 instance 在所有线程中同步
  19. */
  20. private static LazySingleton instance = null;
  21. /**
  22. * 避免在外部被实例化
  23. */
  24. private LazySingleton(){}
  25. public static synchronized LazySingleton getInstance() {
  26. if(instance == null) {
  27. instance = new LazySingleton();
  28. }
  29. return instance;
  30. }
  31. }
  32. ================
  33. /**
  34. * 双重加锁机制
  35. */
  36. public class DoubleLockLazySingleton {
  37. /**
  38. * volatile关键字的含义是:被其所修饰的变量的值不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存来实现,从而确保多个线程能正确的处理该变量。
  39. * 该关键字可能会屏蔽掉虚拟机中的一些代码优化,所以其运行效率可能不是很高,所以,一般情况下,并不建议使用双重加锁机制,酌情使用才是正理!
  40. *
  41. * 更进一步说,其实使用volatile的目的是为了防止暴露一个未初始化的不完整单例实例,导致系统崩溃。
  42. * 因为创建单例实例其实需要经过以下几步:
  43. * 首先分配内存空间、然后将内存空间的首地址指向引用(指针),最后调用构造器创建实例,由于在第二步的时候这个引用(指针)就会变的非null,
  44. * 那么在第三步未执行,真正的单例实例还未创建完成的时候,一个线程过来在第一个校验中为false,将会直接将不完整的实例返回,从而造成系统崩溃。
  45. */
  46. private static volatile DoubleLockLazySingleton instance = null;
  47. private DoubleLockLazySingleton() {}
  48. public static DoubleLockLazySingleton getInstance() {
  49. if(instance == null) {
  50. //区域1
  51. //不同线程去抢夺锁资源
  52. synchronized (DoubleLockLazySingleton.class) {
  53. //区域2
  54. if(instance == null) {
  55. //区域3
  56. /**
  57. * 这里还要进行判断的原因是: 如果两个线程都进入到区域1
  58. * A线程抢到了锁, 实例话对象,如果不加判断, B线程进入同步块也会初始化对象 违反单例原则。
  59. */
  60. instance = new DoubleLockLazySingleton();
  61. }
  62. }
  63. }
  64. //单例存在, 不需要同步操作. 直接返回该引用
  65. return instance;
  66. }
  67. }
  68. ==================
  69. /**
  70. * 静态内部类
  71. * 内部类和其外部类之间没有从属关系, 加载外部类时候不会加载静态内部类, 只有在调用时候才会加载, 创建单例对象返回,实现懒加载。
  72. * 同步问题: 使用静态初始化器的方式,借助jvm实现线程安全
  73. */
  74. public class ClassInnerClassSingleton {
  75. public static class Singleton {
  76. private static ClassInnerClassSingleton instance = new ClassInnerClassSingleton();
  77. }
  78. private ClassInnerClassSingleton() {}
  79. public static ClassInnerClassSingleton getInstance() {
  80. return Singleton.instance;
  81. }
  82. }
  83. public class ClassInnerClassSingleton2{
  84. private static ClassInnerClassSingleton2 instance = null;
  85. static {
  86. instance = new ClassInnerClassSingleton2();
  87. }
  88. private ClassInnerClassSingleton2() {
  89. }
  90. public static ClassInnerClassSingleton2 getInstance() {
  91. return ClassInnerClassSingleton2.instance;
  92. }
  93. public static void main(String[] args) {
  94. new Thread(() -> System.out.println(ClassInnerClassSingleton2.getInstance().hashCode())).start();
  95. new Thread(() -> System.out.println(ClassInnerClassSingleton2.getInstance().hashCode())).start();
  96. new Thread(() -> System.out.println(ClassInnerClassSingleton2.getInstance().hashCode())).start();
  97. }
  98. }

工厂模式:

代码模拟:

=== 简单工厂模式 ===
public interface INoodles {
    /**
     * 描述每种面条啥样的
     */
    public abstract void desc();
}

public class LzNoodles implements INoodles {
    @Override
    public void desc() {
        System.out.println("兰州拉面,兰州特色小吃");
    }
}
public class PaoNoodles implements INoodles {
    @Override
    public void desc() {
        System.out.println("泡面,程序员必备");
    }
}
public class ReganNoodles implements INoodles {
    @Override
    public void desc() {
        System.out.println("红油热干面,武汉特色小吃");
    }
}

/**
 * 简单工厂模式
 * 一家“简单面馆”(简单工厂类)
 */
public class SimpleNoodlesFactory {

    public static final int TYPE_LZ = 1;//兰州拉面
    public static final int TYPE_PM = 2;//泡面
    public static final int TYPE_GK = 3;//热干面

    /**
     * 如果生产对象的方法是static的,这种简单工厂也叫做静态工厂
     * 如果生产对象的方法不是static的,这种简单工厂也叫做实例工厂
     * @param type
     * @return
     */
    public static INoodles createNoodles(int type) {
        switch (type) {
            case 1:
                return new LzNoodles();
            case 2:
                return new PaoNoodles();
            case 3:
                return new ReganNoodles();
            default:
                return new LzNoodles();
        }
    }
}

public class test {
    public static void main(String[] args) {
        /*自己不必关心面条怎么做(怎么new,如何new)让面馆操心去吧(面馆帮我们new)!*/
        INoodles iNoodles = SimpleNoodlesFactory.createNoodles(2);  // 和具体的对象脱离关系
        iNoodles.desc();
    }
}

---------------------
/**
 * 工厂方法模式
 */
public interface INoodlesFactory {
     INoodles createNoodles();
}
public class LzINoodlesFactory implements INoodlesFactory {
    @Override
    public INoodles createNoodles() {
        return new LzNoodles();
    }
}
public class PaoINoodlesFactory implements INoodlesFactory {
    @Override
    public INoodles createNoodles() {
        return new PaoNoodles();
    }
}
public class ReganINoodlesFactory implements INoodlesFactory {
    @Override
    public INoodles createNoodles() {
        return new ReganNoodles();
    }
}
public class Test {
    public static void main(String[] args) {
        INoodlesFactory noodlesFactory = new LzINoodlesFactory();
        INoodles noodles = noodlesFactory.createNoodles();
        noodles.desc();
    }
}

代理模式:

代码模拟:

静态代理:
/**
 * 接口:租房
 */
public interface IRentingHouse {
    void rentHosue();
}
public class RentingHouseImpl implements IRentingHouse {
    @Override
    public void rentHosue() {
        System.out.println("我要租用一室一厅的房子");
    }
}
public class RentingHouseProxy implements IRentingHouse {

    private IRentingHouse rentingHouse;

    public RentingHouseProxy(IRentingHouse rentingHouse) {
        this.rentingHouse = rentingHouse;
    }

    @Override
    public void rentHosue() {
        System.out.println("中介(代理)收取服务费3000元");
        rentingHouse.rentHosue();
        System.out.println("客户信息卖了3毛钱");
    }
}
public static void main(String[] args) {
    IRentingHouse rentingHouse = new RentingHouseImpl();
    RentingHouseProxy rentingHouseProxy = new RentingHouseProxy(rentingHouse);
    rentingHouseProxy.rentHosue();
}
-----------------------------------
动态代理:
jdk代理: 系统自带的代理

    /**
     * Jdk动态代理
     *
     * @param obj 委托对象
     * @return 代理对象
     */
    public Object getJdkProxy(Object obj) {
        // 获取代理对象
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object result = null;
                        // 写增强逻辑
                        System.out.println("中介(代理)收取服务费3000元");
                        // 调用原有业务逻辑
                        result = method.invoke(obj, args);
                        System.out.println("客户信息卖了3毛钱");
                        return result;
                    }
                });
    }
    public static void main(String[] args) {
        IRentingHouse rentingHouse = new RentingHouseImpl();  // 委托对象---委托方
        // 从代理对象工厂获取代理对象
        IRentingHouse jdkProxy = (IRentingHouse) ProxyFactory.getInstance().getJdkProxy(rentingHouse);
        jdkProxy.rentHosue();
    }

--------------------------------------
cglib代理:
    /**
     * 使用cglib动态代理生成代理对象
     *
     * @param obj 委托对象
     * @return
     */
    public Object getCglibProxy(Object obj) {
        return Enhancer.create(obj.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object result = null;
                System.out.println("中介(代理)收取服务费3000元");
                result = method.invoke(obj, objects);
                System.out.println("客户信息卖了3毛钱");
                return result;
            }
        });
    }

    public static void main(String[] args) {
        RentingHouseImpl rentingHouse = new RentingHouseImpl();  // 委托对象
        // 使用工厂来获取代理对象
        RentingHouseImpl cglibProxy = (RentingHouseImpl) ProxyFactory.getInstance().getCglibProxy(rentingHouse);
        cglibProxy.rentHosue();
    }

image.png