常用的设计模式

代理模式

关心的执行的过程
主语对象是被代理对象(就是被调方)
或者说代理模式代理的开头和结尾,因为可以动态的

委派模式

区别于代理模式
关心的是结果,不关心过程
主语对象是委托人(就是调用方)
或者说委派模式代理的中间过程,因为中间过程可以是动态的


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public interface IExector {
void doing();
}

public class ExectorA implements IExector {
@Override
public void doing() {
System.out.println("A开始执行任务");
}
}

public class ExectorB implements IExector{
@Override
public void doing() {
System.out.println("B开始执行任务");
}
}

public class Dispatcher implements IExector{
IExector exector;
Dispatcher(IExector exector){
this.exector = exector;
}
public void doing() {
this.exector.doing();
}
}

工厂模式

主语对象是公共的方法或公共的行为 和 某个具体的bean

  • 结果论:把实现过程封装起来,对于调用者来说,只关心结果
    就比如使用ofo:使用的人只关心我能用到车,至于这个车怎么造的,谁造的,什么时间造的等等,你是不关心的
  • 便于扩展

策略模式

强调:最终的目的都是一样的
主语对象是策略
比如解决一道数学问题,可以有多种解答方式,但是最终的结果都是一样的,这几种方式可以任意切换
再比如超市搞优惠,可以使用会员积分,优惠券、满减等不能优惠方式,但最终结果都是优惠价格
区别于委派模式,策略模式更注重的策略的多样性,委派模式注重的某一种策略
委派模式注重:谁来做
测试模式注重:有多少方式来做

简单工厂

内容大而全,所有的创建方法都在这个类里面

工厂方法

其实就是对简单工厂的一个抽象封装,将各自不同创建内容进行单独封装,并抽象成接口形式



抽象工厂

其实就是对工厂方法的一个再封装,将公共的东西封装成抽象类,将不同的部分由各自子工厂自行实现
其实就是变相的静态代理



单例模式

1.保证系统启动到停止,只产生一个实例(节省资源)
2.在应用中遇到功能性冲突的时候,需要使用单例模式(保证功能不冲突)

  • 配置文件
    针对某一种功能,如果两个配置文件是相同的,那其中有一个就是浪费的,如果不一样,就不知道该用哪个
  • 直系领导
    两个领导给你发命令,你都不知道该听谁的
  • 公历
    是为了和国际同步,如果不同步,那就会有时间差问题
    等等…

单例的几种写法

  • 饿汉模式
1
2
3
4
5
6
7
8
9
10
11
public class Singleton implements java.io.Serializable {

public static Singleton INSTANCE = new Singleton();

protected Singleton() { }

private Object getInstance() {
return INSTANCE;
}

}
  • 懒汉模式 (线程不安全)
1
2
3
4
5
6
7
8
9
10
11
public class Singleton1 {
private Singleton1() {}
private static Singleton1 single = null;

public static Singleton1 getInstance() {
if (single == null) {
single = new Singleton1();
}
return single;
}
}
  • 饿汉模式(静态代码块)
1
2
3
4
5
6
7
8
9
10
11
12
13
pubic class Singleton {
private Singleton instance = null;
static {
instance = new Singleton;
}
private Singleton () {};
public static Singleton getInstance() {
return this.instance;
}
}
// 从上往下(必须声明在前,使用在后)
// 先属性、后方法
// 先静态、后动态
  • 饿汉模式(线程安全,但是每次都需要上锁,大部分情况下用不到)
1
2
3
4
5
6
7
8
9
10
11
public class Singleton2 {
private Singleton2() {}
private static Singleton2 single=null;

public static synchronized Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}
  • 懒汉模式(双重锁检查)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Singleton3 {
//1、第一步先将构造方法私有化
private Singleton3() {}
//2、然后声明一个静态变量保存单例的引用
private static Singleton3 single=null;
//3、通过提供一个静态方法来获得单例的引用
//为了保证多线程环境下的另一种实现方式,双重锁检查
//性能,第一次的时候
public static Singleton3 getInstance() {
if (single == null) {
synchronized (Singleton3.class) {
if (single == null) {
single = new Singleton3();
}
}
}
return single;
}
}
  • 内部类方式 (既解决了线程安全问题,有解决的性能问题,因为是有classLoad保证线程安装的)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Singleton4 {
//1、先声明一个静态内部类
//private 私有的保证别人不能修改
//static 保证全局唯一
private static class LazyHolder {
//final 为了防止内部误操作,代理模式,GgLib的代理模式
private static final Singleton4 INSTANCE = new Singleton4();
}
//2、将默认构造方法私有化
private Singleton4 (){}
//相当于有一个默认的public的无参的构造方法,就意味着在代码中随时都可以new出来

//3、同样提供静态方法获取实例
//final 确保别人不能覆盖
public static final Singleton4 getInstance() {

//方法中的逻辑,是要在用户调用的时候才开始执行的
//方法中实现逻辑需要分配内存,也是调用时才分配的
return LazyHolder.INSTANCE;
}
}
  • 枚举
1
2
3
4
5
6
7
public enum Singleton {
INSTANCE;

Singleton(){

}
}

原型模式

区别于多例,基于拷贝(深拷贝、浅拷贝,反射)
能够直接拷贝其实际内容的数据类型,只支持8个基本数据类型和string,其余都是复制的地址引用。
克隆实际上是一种字节码克隆,而不是重新new一个对象,不走构造方法
反射:性能并不高,一般用在初始化,不会再运行时使用
浅拷贝:只是复制了地址引用,不复制实际的值

1
2
//默认浅克隆,只克隆八大基本数据类型和String
super.clone();

字节码克隆

克隆是不走构造方法的,直接是字节码复制

模板模式

template 就是一个固定的模板,就类似:

  • spring mvc的RestTemplate, restful请求接口的流程是一样的,都是基于http的。
  • java jdbc也定义了一套模板
    1.加载驱动类DriverManager
    2.建立连接
    3.创建语句集(标准语句集、预处理语句集)(Mysql/Oracle/SqlServer等等)
    4.执行语句集
    5.获取结果集ResultSet
    6.ORM

说白了就是对一个东西整个流程的抽象和封装


Jeff-Eric wechat