写在前面,这里仅仅对那些在学习过程中遇到的设计模式进行总结。
单例模式
饿汉模式的代码
package demo.pattern.singleton;
import java.util.*;
public class StarvingSingleton {
private static final StarvingSingleton starvingSingleton = new StarvingSingleton();
private StarvingSingleton(){ }//是一个私有方法,外界无法创建
public static StarvingSingleton getInstance(){
return starvingSingleton;
}
}
懒汉模式的代码
package demo.pattern.singleton;
import java.lang.reflect.InvocationTargetException;
public class LazyDoubleCheckSingleton {
private volatile static LazyDoubleCheckSingleton instance;// volatile 修饰的变量可以被异步的线程所修改
// 使用volatile还有另外一个理由,如果下面三步骤被加速了
// 有可能导致线程1 执行了 3 ,不为空,但是没有实例化2
// 线程2 发现第一个if不是空的,直接返回一个没有实例化的
// 所以加 volatile
private LazyDoubleCheckSingleton(){}
public static LazyDoubleCheckSingleton getInstance(){
// 只在第一次调用的时候才创建唯一的实例
//第一次检测
if (instance==null){
//同步
synchronized (LazyDoubleCheckSingleton.class){
//该类只会有一个,当class被同步锁住之后,其他线程只能等待
//保证了这个类只会创建出一个示例
if (instance == null){
//memory = allocate(); //1.分配对象内存空间
//instance(memory); //2.初始化对象
//instance = memory; //3.设置instance指向刚分配的内存地址,此时instance!=null
instance = new LazyDoubleCheckSingleton();
}
}
}
return instance;
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
System.out.println(LazyDoubleCheckSingleton.getInstance());
System.out.println(LazyDoubleCheckSingleton.getInstance());
}
}
下面这样的代码就无法被反射所攻击,代码写在枚举类中
package demo.pattern.singleton;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class EnumStarvingSingleton {
private EnumStarvingSingleton(){}
public static EnumStarvingSingleton getInstance(){
return ContainerHolder.HOLDER.instance;
}
private enum ContainerHolder{
HOLDER;
private EnumStarvingSingleton instance;
ContainerHolder(){
instance = new EnumStarvingSingleton();
}
}
}
测试代码如下,运行时会报错
package demo.pattern.singleton;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class EnumStarvingSingleton {
private EnumStarvingSingleton(){}
public static EnumStarvingSingleton getInstance(){
return ContainerHolder.HOLDER.instance;
}
private enum ContainerHolder{
HOLDER;
private EnumStarvingSingleton instance;
ContainerHolder(){
instance = new EnumStarvingSingleton();
}
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = ContainerHolder.class;
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
System.out.println(EnumStarvingSingleton.getInstance());
System.out.println(constructor.newInstance());
}
}
由于枚举是存在这个构造方法的,因此我们强制使用这个方法试试
报异常,不能通过反射来创建枚举变量
门面模式
大概知道是怎么一回事即可
这是比较简单的一篇
简单工厂模式
简单来说就是,用户不需要自己去实例化对象,直接可以拿到对象,因为有些对象实例化有时候是特别复杂的,需要很多参数——用户只用买产品就好了,不用知道产品是怎么加工出来的,加工部分就交给工厂去实现了。
这里定义一个鼠标工厂为例子:
package demo.pattern.factory.entity;
import java.util.*;
public interface Mouse {
void sayHi();
}
package demo.pattern.factory.entity;
import java.util.*;
public class HpMouse implements Mouse{
@Override
public void sayHi() {
System.out.println("HP mouse");
}
}
package demo.pattern.factory.entity;
import java.util.*;
public class DeilMouse implements Mouse {
@Override
public void sayHi() {
System.out.println("dell mouse");
}
}
package demo.pattern.factory.simple;
import demo.pattern.factory.entity.DeilMouse;
import demo.pattern.factory.entity.HpMouse;
import demo.pattern.factory.entity.Mouse;
import java.util.*;
public class MouseFactory {
public static Mouse createMouse(int type) {
switch(type){
case 0:return new DeilMouse();
case 1:return new HpMouse();
default: return new DeilMouse();
}
}
}
优点:
可以对创建的对象进行加工,对用户隐藏细节
缺点:
因创建逻辑复杂或者创建对象过多而造成代码臃肿
工厂方法模式
https://blog.csdn.net/carson_ho/article/details/52343584
不使用静态方法了
抽象工厂模式
抽象工厂模式解决了只支持生产一种产品的弊端。对工厂方法模式进行了抽象。