一.Singleton(单例模式)
关于单例模式的写法有很多,我所了解的就有8种方式,我这里主要介绍四种方式(饿汉式,静态内部类的方式,枚举类的方式,以及成熟的懒汉式DCL模式),其他的四种方式都是懒汉式的Synchronize锁的不同位置的方式,最终演变到DCL的模式。
1.饿汉式
饿汉式单例模式是由jvm保障线程安全的,在加载对应类的.class文件,也会将static变量加载到内存中,且.class文件只会被加载一次。
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton(){};
public static Singleton getInstance(){
return INSTANCE;
}
}
2.静态内部类的方式创建单例
这种方式主要是优化饿汉式单例,我们都知道,无论我们是否使用当前单例对象,饿汉式都会将其加载到内存中,而采用静态内部类的方式,我们就可以在getInstance的时候,再去加载单例对象。
public class StaticInsideSingleton {
private StaticInsideSingleton(){};
private static class SingletonHandler{
private static final StaticInsideSingleton INSTANCE = new StaticInsideSingleton();
}
public static StaticInsideSingleton getInstance(){
return SingletonHandler.INSTANCE;
}
}
3.使用枚举类的方式创建单例模式
由于枚举类没有构造函数,所以可以防止通过反序列化,反射的方式创建一个新的对象,反序列化得到的对象也是之前的对象,所以说枚举的方式才是最好的方式,但是没见人用过,我也仅仅是了解这么个方式而已。
public enum EnumSingleton {
INSTANC;
}
4.DCL(懒汉式,这个模式的考点其实很多的)
问题:
1).synchronize为什么使用代码块的方式,不在方法上加?
效率问题,需要加锁的地方在加锁。
2).为什么synchronize的位置为什么要放在if条件下面?
避免所有的线程都去争夺锁资源对象,可以隔离大部分的线程,避免锁资源争抢过高
3).为什么synchronize代码块中还需要一个if条件?
这个问题很简单,不做控制的化,会创建出不同的对象。
4).可以去除volatile字段么?
答案是否定的,因为volatile,两大特征,可见性,禁止指令重排序的问题,如果不加,在对象创建的过程中,出现了Java汇编指令重排序的问题,会导致有的线程获得半初始化的对象。
public class DCLSingleton {
private static volatile DCLSingleton instance;
private DCLSingleton(){};
public static DCLSingleton getInstance(){
if(instance == null){
synchronized(DCLSingleton.class){
if(instance == null){
instance = new DCLSingleton();
}
}
}
return instance;
}
}
二.Strategy(策略模式)
strategy模式:做一件事的不同策略。
jdk中的案例是:Comparator(比较器接口),可以实现Comparator接口,提供不同的比较策略。
为什么要使用策略模式:如果不用strategy我们肯定也能够开发,但是如果,我们代码中的某一个行为需要用不同的方式或者是新增不同的方式的时候,我们就需要更改原来的代码,strategy模式就是少量更改原有的代码,功能扩展的时候很方便。
现阶段,我实际开发的项目中,对于不同节点的任务提交,采用策略模式,提供了三种任务提交的策略,经办,复核,完结。
我做的tank大战小游戏项目中,对于主站tank的开火方式也提供了两种策略,默认的,四个方向的。对应的代码:主站tank的开火策略.gitee
策略模式在开发使用的频率也是很高的。
三.工厂模式
工厂模式分为:简单工厂,工厂方法,抽象工厂
简单工厂:直接new的就可以称之为简单工厂
工厂方法:针对不同的对象创建提供一个工厂,便于单个产品的扩展。
抽象工厂:一系列产品族的创建提供一个工厂,便于产品族的扩展
工厂模式就是可以定制生产过程。
项目实战:使用抽象工厂tank的一键换肤模式。
地址:tank,bullet,expode的一键换肤代码.gitee
四.Facade(门面),Meditor(调停者模式)
这两个模式很好理解:一个项目中很多的业务,业务之间需要交互的情况比较紧密,我们可以提供一个Facade,Facade是对外的称呼,外部系统访问我们系统的时候。对内的称呼为Meditor,这样各个业务之间不需要直接交互,通过Meditor进行交互,业务之间的耦合性降低,而且新增的业务需要与之前的业务进行交互的化,修改的代码会比较少,这就是对修改关闭,对扩展开放。
应用场景:将之前的TankFrame中与tank、bullet、Exploed,的交互抽取出来,GameModel,GameModel再与tank、bullet、Exploed进行交互。
Facade,Meditor应用实战.gitee