想说的话:
在大学的时候曾经学过这23种设计模式,但是那时没啥编程经验,糊里糊涂过了一遍,没多久就忘记了,工作之后将精力主要集中在学习新技术上,比如springboot,cloud,docker,vue。毕业两年后去面试,发现设计模式还是java程序员需要迈过的一道坎,面试的时候问到代理模式和适配器模式有什么区别,你在工作中用到了什么设计模式,怎么用的?答不上来的特别尴尬,所以决定重新学习这几种设计模式,争取在工作中使用上。
本文所有案例代码
码云:https://gitee.com/helloworld6379/designPattern
Github:Github地址
设计模式概述
1 设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验,模式不是代码,而是某类问题的通
用解决方案,设计模式(Design pattern)代表了最佳的实践。这些解决方案是众多软件开发人员经过相当长的
一段时间的试验和错误总结出来的。
2 设计模式的本质提高 软件的维护性,通用性和扩展性,并降低软件的复杂度。
3 设计模式并不局限于某种语言,java,php,c++ 都有设计模式.
设计模式类型
设计模式分为三种类型,共 23 种
1 创建型模式:单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式。
2 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
3 行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter 模式)、状态模式、策略模式、职责链模式(责任链模式)。
简单介绍
- 代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象.这样做的好处 是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
- 被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象
- 代理模式有不同的形式, 主要有三种 静态代理、动态代理 (JDK 代理、接口代理)和 Cglib 代理 (可以在内存 动态的创建对象,而不需要实现接口, 属于动态代理的范畴) 。
静态代理
静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类。
以电脑快捷方式为例:
/**
* @Description 被代理对象接口
* @Author: LiuXing
* @Date: 2020/5/28 21:32
*/
public interface Application {
void watchMovie();
}
/**
* @Description 被代理对象实体类
* @Author: LiuXing
* @Date: 2020/5/28 21:32
*/
public class KuaiBo implements Application {
@Override
public void watchMovie() {
System.out.println("使用快播看小电影。");
}
}
/**
* @Description 代理对象
* @Author: LiuXing
* @Date: 2020/5/28 21:32
*/
public class KuaiBoInk implements Application{
private Application app;
public KuaiBoInk(Application app){
this.app = app;
}
@Override
public void watchMovie() {
app.watchMovie();
}
}
/**
* @Description 静态代理模式
* @Author: LiuXing
* @Date: 2020/5/28 21:32
*/
public class StaticProxyTest {
public static void main(String[] args) {
//创建目标对象(被代理对象)
KuaiBo kuaiBo = new KuaiBo();
//创建代理对象, 同时将被代理对象传递给代理对象
KuaiBoInk kuaiBoInk = new KuaiBoInk(kuaiBo);
//通过代理对象,调用到被代理对象的方法
// 即:执行的是代理对象的方法,代理对象再去调用目标对象的方法
kuaiBoInk.watchMovie();
}
}
动态代理
- 代理对象,不需要实现接口,但是目标对象要实现接口,否则不能用动态代理 。
- 代理对象的生成,是利用 JDK 的 API,动态的在内存中构建代理对象 。
- 动态代理也叫做:JDK 代理、接口代理。
/**
* @Description 被代理对象接口
* @Author: LiuXing
* @Date: 2020/5/28 21:32
*/
public interface Application {
void watchMovie();
void downloadMovie(String movie);
}
/**
* @Description 被代理对象实体类
* @Author: LiuXing
* @Date: 2020/5/28 21:32
*/
public class KuaiBo implements Application {
@Override
public void watchMovie() {
System.out.println("使用快播看小电影。");
}
@Override
public void downloadMovie(String movie) {
System.out.println("下载" + movie);
}
}
package com.fighting.pattern.proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Description 代理工厂
* @Author: LiuXing
* @Date: 2020/5/28 21:32
*/
public class ProxyFactory {
//维护一个目标对象Object
private Object target;
//构造器,对target进行初始化
public ProxyFactory(Object target) {
this.target = target;
}
//给目标对象 生成一个代理对象
public Object getProxyInstance() {
//说明
/** publicstaticObjectnewProxyInstance(ClassLoaderloader, Class<?>[]interfaces, InvocationHandlerh)
//1.ClassLoaderloader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
//2.Class<?>[]interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
//3.InvocationHandlerh: 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK 代理开始~~");
//反射机制调用目标对象的方法
Object invoke = method.invoke(target, args);
System.out.println("JDK 代理提交");
return invoke;
}
});
}
}
/**
* @Description 动态代理模式测试
* @Author: LiuXing
* @Date: 2020/5/28 21:32
*/
public class StaticProxyTest {
public static void main(String[] args) {
Application kuaiBo = new KuaiBo();
Application proxyInstance = (Application)new ProxyFactory(kuaiBo).getProxyInstance();
//proxyInstance=classcom.sun.proxy.$Proxy0 内存中动态生成了代理对象
System.out.println("proxyInstance = " + proxyInstance.getClass());
proxyInstance.downloadMovie("十六歳のロリ嬌羞初体験.avi");
proxyInstance.watchMovie();
}
}