0.设计模式的设计原则
S:单一职责原则
O:开闭原则 open-close 新增代码、修改代码,我们要解决一个问题,新增代码好还是修改代码好
L:里氏替代原则。凡是子类出现的地方都可以使用父类来进行接收。父类和子类之间的关系,子类不要重写父类的方法;如果子类要重写父类的方法,父类的方法定义为抽象方法。
I:接口隔离原则。不同的功能放在不同的接口里。更侧重于接口。**避免写大接口(多),成本高**
D : 依赖倒置原则。 具体和抽象。具体依赖于抽象
1.单例设计模式
单实例对象->在应用程序中是单个实例,在应用程序中取出实例,始终是同一个
节约资源
移植成本降低(就只需要修改在容器里的那一个对象,或者说取另一个对象 ,因为是单例,所以取得的都是那一个;)
我们如何去写一个单例?
-
构造方法私有
-
类里提供方法让外部能够获得实例
-
维护成员变量实例(包含自身类型的成员变量)
1.4线程安全的立即加载
也就是,不触发静态内部类的时候就不会进行内加载(符合懒加载的原理)
因此静态内部类的静态代码块符合一切要求;
静态代码块保证了线程安全;
静态内部类保证的懒加载;
package com.cskaoyan.z_desiner;
/**
* @author looper
* @
**/
public class Mydesigner {
//1构造器私有化
private Mydesigner() {
}
//2提供一个获得的方法
public static Mydesigner getIns() {
Mydesigner mydesigner = Inner.getMydesigner();
return mydesigner;
}
//3线程安全
//4懒加载
static class Inner {
private static Mydesigner mydesigner;
static {
mydesigner = new Mydesigner();
}
static Mydesigner getMydesigner() {
return mydesigner;
}
}
}
package com.cskaoyan.z_desiner;
/**
* @author looper
* @
*
* 线程安全的饿汉式
**/
public class Mydesigner2 {
private static Mydesigner2 mydesigner2;
static {
mydesigner2 = new Mydesigner2();
}
//1构造器私有化
private Mydesigner2() {
}
//2提供一个获得的方法
public static Mydesigner2 getIns() {
return mydesigner2;
}
//3线程安全
//4懒加载
}
package com.cskaoyan.z_desiner;
/**
* @author looper
* @
*
* 线程安全的懒汉式,但是效率问题
**/
public class Mydesigner3 {
private static Mydesigner3 mydesigner3;
private Mydesigner3() {
}
public synchronized Mydesigner3 getIns() {
if (mydesigner3 == null) {
mydesigner3 = new Mydesigner3();
}
return mydesigner3;
}
//3线程安全
//4懒加载
}
2.工厂设计模式->factory
生产实例对象-->可以隐藏细节
2.1简单工厂
2.2工厂方法
一个接口--钱币工厂,一个接口---money
3.代理设计模式-->proxy
什么是代理?帮忙 👉 帮别人去做别人本来要做的事情
李要买早餐,让陆 帮他买,陆就是代理
李:委托方
陆:代理方
代理方:帮委托方去做委托方本身要去做的事情,还可以做额外的事情(增强)
陆多加了卤蛋,这个卤蛋就是额外的事情。这个卤蛋才是最核心的部分
为什么要使用代理?
针对于委托类每一个要做的事情,都会去做一个相同的增强
增强的是委托类的所有方法,都去做相同的增强。
解决开发过程中的繁琐 👉 举了个栗子:sqlSession的获得、获得Mapper、commit、close
(其实也就是spring的控制层在调用服务层的时候,服务层返回一个服务层的代理对象,这个对象里面的dao也已经被封装好了,所以在控制层就可以直接调用实例对象了)
方法增强
3.1静态代理类
剪切板 ctrl+shift+v 查找历史粘贴板
1.委托类作为成员变量
2.委托类作为父类,通过super来调用方法
小结:
- 代理对象执行的方法才是增强的方法
- 代理对象的方法,执行委托类的方法+增强方法
- 代理类中方法和委托类的方法相同(想想康师傅的实现一个公共接口就行)
3.2动态代理
(不改方法代码的情况下,对一个方法做增强,并且通过反射可以做到对传入类的属性方法赋值(spring注入))
(代理就是,实现同一个接口(jdk),一个类对另一个类里的一个方法做增强(存为成员变量,构造器赋值,,然后调用方法的时候顺便调用被代理类的方法)(cblib是继承方式的super.method())
(所以动态的就是,根据传入类的字节码对象,然后获得所有的方法(底层已经帮忙做了),然后在method.invoke()前后写增强逻辑,最后返回一个代理类的对象)
代理对象点哪个方法就反射哪个方法,在方法执行之前会执行增强的方法
自动生成的代理类
一个方法传入代理类的method方法(类对象,方法名,参数),
利用类对象生成对象,方法名反射得到方法,利用参数,然后invoke方法,写加强的逻辑
2.3.2JDK动态代理
实现一个共同接口,代理对象的接收要用接口来接收(代理类与委托类之间只是有共同接口(兄弟关系))
动态代理开发核心:
invocationhandler的invoke方法
有一行固定写法:method.invoke
这此行的前后进行自定义增强的代码
2.33CGlib代理动态
代理类继承了委托类(代理类需要做子类,所以可以直接返回父类)
代理类对象可以使用委托类对象来接收,当然你也可以使用接口来接收
@Test
public void mytest2() {
Ray ray = new Ray();
//获得代理对象
Ray proxy = (Ray) Enhancer.create(Ray.class, new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Object invoke = method.invoke(ray, objects);
System.out.println("四个卤蛋");
return invoke;
}
});
proxy.drink();
}
3.生成代理类的字节码文件
1.
this就是上图的proxy
--
和JDK动态代理里不同的点:
-
获得代理对象使用的类和方法不同
-
InvocationHandler使用的是不同的包下的接口
-
代理对象的接收方式不同
4.建造者模式builder
工厂侧重于隐藏实现的细节,
建造者更擅长于需要使用者提供属性值
- 套路:
- 1.设置参数
- 2.获得结果
-
快捷键
ctrl+shift+v 找到历史复制值
shift+enter 快速另起一行
ctrl + shift + enter 补全代码并调整格式
alt + shift + ↑ 当前行的代码上移一行
alt + shift + ↓ 当前行的代码下移一行
ctrl + alt + v 快速提取变量
ctrl + alt + shift + c 复制全限定类名
ctrl + shift + f 全局搜索(侧重于内容)
双击shift 全局搜索(侧重于文件)