设计模式
1、单例模式
1)懒汉式

多线程的情况下就会出问题,例如两个线程同时判断Instance是否为空,此时Instance还没创建好,那么两者都会创建一个实例
2)在1)的基础上加上同步锁

每次通过getIns()方法获取单例时,都有一个试图去获取同步锁的过程,而加锁是很费时的,能免就免
3)双重校验锁

volatile的作用:new操作在底层分为三步:1、为对象分配空间。2、实例化对象。3、把sing引用指向分配的内存空间。如果没有volatile,则可能指令重排列1,3,2,一个线程执行到3时,sing已经不是null,此时线程2判断sing!=null,则直接返回sing的引用,但现在实例对象还没有初始化完成,此时线程2使用sing可能会造成程序异常。为什么需要两次判空?第一次判断是为了验证是否创建对象,避免多线程访问时每个线程都加锁,提升效率。第二次判断是为了避免重复创建单例,因为可能会存在多个线程通过了第一次判断在等待锁,来创建新的实例对象
4) 饿汉

sing为static类型,在类装载时就实例化
5) 静态内部类

利用了classloader的机制来保证初始化sing时只有一个线程,跟4)不一样的地方在于,4)只要Single类被装载了,那么sing实例就会被实例化,而这种方法是Single类被装载了,sing不一定被初始化,因为SingleHolder没有被主动使用,只有通过调用getIns()方法时才会显示装载SingleHolder类,从而实例化sing。想象一下如果实例化sing很耗资源,想延迟加载。这个方法就很合适。
对于java类加载机制来说,当第一次访问类的静态字段的时候,会触发类加载,并且同一个类只加载一次。静态内部类也是如此,只会被加载一次,类加载过程由类加载器负责加锁,从而保证线程安全
6)枚举方式

能避免多线程同步问题,而且能防止反序列化重新创建对象
2、适配器模式
是7种结构型模式的起源:将某个类的接口转换成客户端期望的另一个接口表示,目的是消除接口不匹配造成的类兼容性问题,主要分三类:类的适配器模式,对象的适配器模式,接口的适配器模式。
1)先看类的适配器模式:有一个source类,拥有一个方法待适配,目标接口是target,通过adapter类,将source的功能扩展到target里:


这样target接口的实现类就具有了source类的功能。
2)对象的适配器模式,思路和上面相同,只是把adapter类修改下,这次不是继承source类,而是持有source类的实例。

3)接口的适配器模式:有时我们写的接口中有多个方法,而写其实现类时,必须实现其所有方法,有的方法不是我们想要的,过于麻烦。所以引入接口的适配器模式,借助一个抽象类,该抽象类实现了该接口,实现了所有的方法,我们只和该抽象类联系,继承该抽象类,重写需要的方法。


总结:类的适配器模式:当希望一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新的类,继承原有类,实现新的接口即可
对象的适配器模式:当希望一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,调用实例的方法就行。
接口的适配器模式:当不希望实现一个接口中所有的方法时,可以创建一个抽象类Wrapper,实现所有方法,我们写的别的类继承抽象类即可。
3、代理模式:就是多一个代理类出来,替原对象进行一些操作



4、模板方法模式
一个抽象类公开定义了方法。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行
public abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
//模板
public final void play(){
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
}
}
public class Football extends Game {
@Override
void endPlay() {
System.out.println("Football Game Finished!");
}
@Override
void initialize() {
System.out.println("Football Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
public static void main(String[] args) {
Game game = new Football();
game.play();
}
}
5、工厂模式
定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行
interface Shape {
void draw();
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
class Square implements Shape {
@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}
public class ShapeFactory {
//使用 getShape 方法获取形状类型的对象
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//获取 Circle 的对象,并调用它的 draw 方法
Shape shape1 = shapeFactory.getShape("CIRCLE");
//调用 Circle 的 draw 方法
shape1.draw();
//获取 Rectangle 的对象,并调用它的 draw 方法
Shape shape2 = shapeFactory.getShape("RECTANGLE");
//调用 Rectangle 的 draw 方法
shape2.draw();
//获取 Square 的对象,并调用它的 draw 方法
Shape shape3 = shapeFactory.getShape("SQUARE");
//调用 Square 的 draw 方法
shape3.draw();
}
}
输出:
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
6、责任链模式(ms实现,spring filter链,Interceptor链)
优点:
降低各个处理器之间耦合度
按需控制请求处理顺序,实现流程编排
扩展性高,动态新增减少处理器,不需改动核心代码
浙公网安备 33010602011771号