1. Singleton单例模式
只需要一个实例
构造器私有
1.1 饿汉式
JVM保证了线程安全
缺点:类装载时就完成了实例化,不管有没有用
public class Hungry() {
private static final Hungry INSTANCE = new HUNGRY();
private Hungry() {}
public static Hungry getInstance() { return INSTANCE; }
}
1.2 懒汉式
1.2.1 用的时候再实例化:
// 缺点:线程不安全
public class Lazy01() {
private static Lazy01 INSTANCE;
private Lazy01() {}
public static Lazy01 getInstance() {
if (INSTANCE == null) { // 几个线程可以同时判断为null,从而创建多个实例
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Lazy01();
}
return INSTANCE;
}
}
1.2.2 给 getInstance()
加锁:
public class Lazy02() {
private static Lazy02 INSTANCE;
private Lazy02() {}
// 缺点:锁的粒度太粗
public static synchronized Lazy02 getInstance() {
// ...
// 很多业务逻辑
// ...
if (INSTANCE == null) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Lazy02();
}
return INSTANCE;
}
}
1.2.3 在实例化的地方加锁:
public class Lazy03() {
private static Lazy03 INSTANCE;
private Lazy03() {}
public static Lazy03 getInstance() {
// ...
// 很多业务逻辑
// ...
if (INSTANCE == null) {
// 缺点:还是线程不安全
synchronized (Lazy03.class) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Lazy03();
}
}
return INSTANCE;
}
}
1.2.4 DCL (Double Check Lock)
public class DCL() {
private static volatile DCL INSTANCE;
private DCL() {}
public static Lazy03 getInstance() {
// ...
// 很多业务逻辑
// ...
if (INSTANCE == null) { // 这层与线程安全无关,是为了提高效率
synchronized (DCL.class) {
if (INSTANCE == null) { // 双重检查
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new DCL();
}
}
}
return INSTANCE;
}
}
- DCL需不需要加
volatile
?
对象创建的过程(大体):
- 分配内存 (对象的成员变量(这里是INSTANCE)被赋予默认值)
- 初始化 -- INSTANCE被赋予真实值
- 建立关联 -- 将变量名指向INSTANCE
2,3可能出现指令重排序的现象,也就是说,一个线程中对象在半初始化的时候就与INSTANCE建立联系了,另一个线程发现INSTANCE不为空,则直接拿到了半初始化的INSTANCE,所以需要 volatile
来禁止指令的重排序!
1.3 静态内部类
public class Single() {
private Single() {}
// Single的静态内部类在Single加载时不会被加载
private static class SingleHolder {
// 只有在Single类的内部才能调用Single的私有构造
private final static Single INSTANCE = new Single();
}
// 只有调用此方法才会加载SingleHolder,并且return的是SingleHolder中的静态变量
// JVM保证Class类只会被加载一次,保证单例
public static Single getInstance() { return SingleHolder.INSTANCE; }
}
1.4 枚举(*)
public enum Single02() {
// 不仅线程同步,还可以防止反序列化
INSTANCE;
public void m() {}
public static void main(Stringp[] args) {
Single02.INSTANCE;
}
}
后期可以交给Spring来构造单例的Bean
2. 责任链模式
2.1 基本思想
将一条message经过一系列过滤审查程序后加入数据库
// 首先有一个过滤器接口
class interface Filter {
boolean doFilter(String msg);
}
// 一些过滤器实现
class EncodingCharacterFilter implements Filter {
public boolean doFilter(String msg) {
...
return true;
}
}
class SensitiveFilter implements Filter {
// 在一些过滤器中,若检测到某些元素,则直接放弃将这条信息加入数据库
public boolean doFilter(String msg) {
if (...) { return false; }
return true;
}
}
class OtherFilter01 implements Filter {...}
class OtherFilter02 implements Filter {...}
// 因为是一系列过滤器,所以将这些filter放在一个filterChain上
class FilterChain implements Filter {
List<Filter> filters;
public Filter() { this.filters = new ArrayList<>(); }
public void addFilter(Filter filter) { this.filters.add(filter); }
// 遍历chain上的所有filter,若其中一个filter返回false,则直接停止
public boolean doFilter(String msg) {
boolean flag = true;
for (Filter f : this.filters) {
flag = f.doFilter(msg);
if (!flag) { return flag; }
}
return flag;
}
}
public static void main(String[] args) {
FilterChain fc01 = new FilterChain();
fc01.addFilter(new EncodingCharacterFilter());
fc01.addFilter(new SensitiveFilter());
FilterChain fc02 = new FilterChain();
fc02.addFilter(new OtherFilter01());
fc02.addFilter(new OtherFilter02());
// 这里因为FilterChain本身也实现了Filter接口,所以一整个FilterChain也可以
// 被加入到另一个FilterChain中
fc01.addFilter(fc02);
String msg = "I want a bomb!"
fc01.doFilter(msg);
}
2.2 责任链在javax.servlet中的(粗略)实现方式:
// 这个类实现了FilterChain接口
public final class ApplicationFilterChain implements FilterChain
// 其中的这个方法接受request和response
// 并在做出一些判读后,调用internalDoFilter()方法
public void doFilter(ServletRequest request, ServletResponse response) {
if (...) {
...
} else {
this.internalDoFilter(request, response);
}
}
private void internalDoFilter(ServletRequest request, ServletResponse response) {
// 先判断执行到哪一个filter了
if (this.pos < this.n) {// 若还没有执行完
...
// 从Filter的list中那Filter,并increment pos
ApplicationFilterConfig filterConfig = this.filters[this.pos++];
...
Filter filter = filterConfig.getFilter();
...
// 拿到Filter后调用Filter的doFilter()方法
// *这里chain会将自己作为参数传入doFilter
filter.doFilter(request, response, this);
} else {
// 若还执行完了
// 执行servlet
this.servlet.service(request, response);
}
}
// 在Filter的doFilter中,完成过滤逻辑后
// 会用被传入的FilterChain调用doFilter(),进行下一个过滤器
// 而这时chain中的pos已经是被加一了的
// 实现了过滤器的遍历
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
...
// **这里若在重写时不调用chain.doFilter
// 过滤终止,所以就不用return boolean了
chain.doFilter(request, response);
}
2.3 递归思想
需求:先按1,2,3的顺序处理request请求,再按3,2,1的顺序处理response响应。
class interface Filter {
void doFilter(Request req, Response resp, FilterChain chain);
}
class FilterChain implements Filter {
private int pos = 0;
private List<Filter> filters = ArrayList<>();
public void doFilter(Request req, Response resp, FilterChain chain) {
if (this.pos > filters.size()) { return; }
filters.get(pos++).doFilter(req, resp, this);
}
}
class FilterImpl01 implements Filter {
public void doFilter(Request req, Response resp, FilterChain chain) {
processRequest(req);
chain.doFilter(req, resp, chain);
processResponse(resp);
}
}
class FilterImpl02 implements Filter {...}
class FilterImpl03 implements Filter {...}
public static void main(String[] args) {
FilterChain fc = new FilterChain();
fc.add(new FilterImpl01);
fc.add(new FilterImpl02);
fc.add(new FilterImpl03);
fc.doFilter(req, resp, fc);
}
3. Factory工厂模式
3.1 SimpleFactory
不是一种设计模式!
场景:需要通过条件判断来实例化某一个对象
if ("car".equals(name)) {
Vehicle vehicle = new Car();
} else if ("plane".equals(name)) {
Vehicle vehicle = new Plane();
} else if ("Tank".equals(name)) {
Vehicle vehicle = new Tank();
}
如果在方法中像这样写死,难以维护。可以将这个实例化的过程抽出来
class SimpleVehicleFactory {
Vehicle vehicle;
public Vehicle create(String name) {
if ("car".equals(name)) {
vehicle = new Car();
} else if ("plane".equals(name)) {
vehicle = new Plane();
} else if ("Tank".equals(name)) {
vehicle = new Tank();
}
return vehicle;
}
}
这样若程序中有多处使用这个实例化的过程,只需要修改这个工厂内方法一处的代码。
3.2 Factory Method Pattern
一个抽象类(Creator)中有对于另一个类(Product)的实例化与使用,在Creator中,实现所有使用了product的方法,但将实例化Product的方法变成抽象的方法,并将实现这个抽象方法的任务交给各个Creator的子类ConcreteCreator。
在下面的例子中,VehicleStore的test()方法需要先将vehicle实例化,再使用vehicle的各个方法。那么具体是哪一种vehicle呢?VehicleStore只规定了在vehicle实例化后如何使用vehicle对象,而将vehicle的实例化过程,交给子类去实现,它的各个子类,只需要实现create()这个抽象方法就可以实例化并使用具体的vehicle。
-
将生产方法(实例化的过程)抽象并交给子类去实现的这种模式就叫做Factory Method Pattern,这里create() 就是the factory method。这种模式,分离了对象的创建和使用 -- test()方法并不知道它所使用的vehicle究竟是具体的哪一种。
The Factory Method Pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
一个具体的Store,如CarStore,从原来需要依赖具体的Car对象,到如今只需要依赖Vehicle的abstract对象;一个具体的Car对象,也需要依赖Vehicle的abstract对象。这样就做到了依赖反转,Dependency Inversion。
这个模式的好处是,扩展更多的ConcreteProduct非常的容易(扩展更多的vehicle种类),只需要一个继承Vehicle的类和一个继承VehicleStore并实现create()方法的类,并不对原有的代码进行任何修改。
// Product
public abstract class Vehicle {
String name;
void fillGas();
void drive();
void pullOver();
}
// ConcreteProduct
public class Car extends Vehicle {
String name = "car";
}
public class Plane extends Vehicle {...}
public class Tank extends Vehicle {...}
// Creator
public abstract class VehicleStore {
public void testVehicle() {
Vehicle vehicle = this.create();
vehicle.fillGas();
vehicle.drive();
vehicle.pullOver();
}
// 将生产过程交给子类
protected abstract Vehicle create();
}
// ConcreteCreator
public class CarStore extends VehicleStore {
Vehicle create() {
return new Car();
}
}
public class PlaneStore extends VehicleStore {
Vehicle create() {
return new Plane();
}
}
public class TankStore extends VehicleStore {...}
public static void main(String[] args) {
VehicleStore store = new CarStore();
store.test();
}
3.3 Abstract Factory Pattern
一个武装人员需要一把步枪,一把手枪和一把机枪,但一个警察和一个恐怖分子所需的这三把武器具体的种类都不一样,如警察的步枪为M416,但恐怖分子的步枪为AKM。还有可能有其他种类的武装人员,如特种兵,劫匪等,但他们作为武装人员,都需要一把步枪,一把手枪和一把机枪。
所以我们需要一个接口(creator),这个接口规定了我们需要生产哪些抽象类(Product)(如,需要一把步枪,一把手枪和一把机枪),而这个接口的实现类(ConcreteCreator)实现这些生产方法,生产出抽象类的具体类(ConcreteProduct),如警察的接口实现类户生产M416作为步枪,P1911作为手枪,M249作为机枪。
-
这个模式就是抽象工厂模式
An Abstract Factory gives us an interface for creating a family of products.
That allows us to implement a variety of factories that produce products meant for different contexts—such as different regions, different operating systems, or different look and feels.
缺点是接口规定好了需要哪些抽象类,若要添加抽象类,就需要修改所有接口的实现类。
// 接口规定了生产哪些抽象类
public interface WeaponFactory {
AR createAR();
Pistol createPistol();
MachineGun createMachineGun();
}
// 抽象类和继承他们的一些具体的类
public abstract class AR {}
public class AKM extends AR {}
public class M416 extens AR {}
public abstract class Pistol {}
public class DesertEagle extends Pistol {}
public class P1911 extends Pistol {}
public abstract class MachineGun {}
public class M249 extends MachineGun {}
public class Gantling extends MachineGun {}
public class PoliceWeaponFactory implements WeaponFactory {
public AR createAR() {
return new M416();
}
public Pistol createPistol() {
return new P1911();
}
public MachineGun createMachineGun() {
return M248;
}
}
public class TerroristWeaponFactory implements WeaponFactory {
public AR createAR() {
return new AKM();
}
public Pistol createPistol() {
return new DesertEagle();
}
public MachineGun createMachineGun() {
return new Gatline();
}
}
// 只需要修改工厂的实现类,就可以武装不同的人员
public void arm(Man man) {
WeaponFactory factory = new PoliceWeaponFactory();
man.AR = factory.createAR();
man.pistol = factory.createPistol();
man.machineGun = factory.createMachineGun();
}