1、单例
①、懒汉式
public class SingleModel {
private static SingleModel instance;
private SingleModel() {
}
public static SingleModel getInstance(){
if (instance == null){
instance = new SingleModel();
}
return instance;
}
}
顾名思义,就是在使用的时候才会去创建对象,比较懒
②、饿汉式
public class SingleModel2 {
private static SingleModel2 instance = new SingleModel2();
private SingleModel2(){}
public static SingleModel2 getInstance(){
return instance;
}
}
一开始就创建好对象
构造函数私有化是为了防止每次通过getInstance()方法获取对象时导致调用公共构造函数导致创建对象不唯一,这种情况下就不是单例模式了。
3、生产者与消费者
基于synchronized的等待唤醒机制
public class ProAndConsumerModel1 {
private static int count = 0;
private static Object object = new Object();
public static void main(String[] args) {
while (true){
new Thread(() -> {
while (true){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object){
while (count == 10){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("生产消息,共有:" + ++count + " 条数据");
object.notify();
}
}
}).start();
new Thread(() -> {
while (true){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (object){
while (count == 0){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费消息:" + count--);
object.notify();
}
}
}).start();
}
}
}
基于信号量
public class ProAndConsumerModel2 {
private static int count = 0;
private static Semaphore proSemaphore = new Semaphore(10);
private static Semaphore conSemaphore = new Semaphore(0);
private static Semaphore mutex = new Semaphore(1);
public static void main(String[] args) {
while (true){
new Thread(() -> {
while (true){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
proSemaphore.acquire();
mutex.acquire();
System.out.println("生产消息:" + ++count + "... ...");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
conSemaphore.release();
mutex.release();
}
}
}).start();
new Thread(() -> {
while (true){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
conSemaphore.acquire();
mutex.acquire();
System.out.println("... ... 消费消息:" + count--);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
proSemaphore.release();
mutex.release();
}
}
}).start();
}
}
}
生产者与消费者的应用场景参考:
生产者消费者模型应用场景及优势?
3、代理
①、静态代理
静态代理模式需要目标对象和代理对象实现同一个接口,虽然可以做到在不修改目标对象功能的前提下对目标功能进行扩展,但是代理对象与目标对象需要实现相同的接口,代理类很多,而且当接口方法改变时目标对象与代理对象都需要维护。
②、动态代理
为解决静态代理的缺点可以使用动态代理,动态代理代理对象不需要实现接口,是利用JDK的API在内存中动态的创建代理对象。
代理对象简单实现如下:
public class ProxyFactory {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
(proxy, method, args) -> {
System.out.println("开始增强");
Object res = method.invoke(target,args);
System.out.println("结束增强");
return res;
});
}
}
动态代理中目标对象要实现接口,而代理对象不需要实现接口
③、Cglib代理
当目标对象是一个单独的对象而没有实现具体的接口时就没办法使用动态代理或者静态代理,此时可以使用目标对象子类来实现代理,也就是cglib代理
关于代理模式推荐阅读:
Java的三种代理模式
4、工厂
推荐阅读:
Java设计模式之工厂模式