为其他对象提供一种代理控制此对象的访问
若一个对象不适合直接引用另一个对象,
代理对象在客户端和目标对象之间起到中介作用
组成:
抽象角色:通过接口 抽象类 真实角色实现了哪些方法
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法
可以附加自己的操作
真实角色:实现抽象角色,定义业务逻辑,供代理角色来调用
代理模式分类
静态代理
动态代理
JDK动态代理
cglib动态代理
静态代理: 抽象角色固定, 代理角色和代理的真实角色是固定。
动态代理
通过反射机制来实现的,代理角色不在是固定的角色,而是一个通用的工具类,还可以代理很多操作
动态代理是在静态代理的基础上,代理的真实角色由设置好的固定的一个变成自由的多个,实现更广泛的应用。
动态代理的代理角色类Proxyutil需要实现接口InvocationHandler
public class ProxyUtil经纪人 implements InvocationHandler { private Object obj; public Object newProxyInstance(Object obj){ this.obj = obj; return Proxy.newProxyInstance(this.obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); }; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(obj,args); } }
/**
* 代理角色:
*/
public class 经纪人 implements InvocationHandler {
//真实角色,由于任何角色都可以使用此工具类,所以将真实角色定义成Object
private Object obj;/**
* 功能:创建真实角色,通过调用方法,获取代理角色代理的对象
* @return
*/
public Object newProxyInstance(Object obj){
this.obj = obj;
/*
Proxy这个类是用于设置代理
newProxyInstance(
ClassLoader loader, 参数1:类的加载器
Class>[] interfaces, 参数2.类的接口
InvocationHandler h) 参数3: 本类的实例通过 newProxyInstance方法获取真实对象的接口,从而创建代理实例
*/
Object o = Proxy.newProxyInstance(
this.obj.getClass().getClassLoader(), //我是谁? 真实对象
obj.getClass().getInterfaces(), //我干爹是谁? 真实对象实现的接口
this // 代理是谁, 你要实现哪个接口
);
return o;
}//用反射的方法调用真实角色中的方法
/**
*
* @param proxy 代理对象
* @param method 代理有哪些方法
* @param args 包含传入代理实例上方法调用的参数值的对象数组
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(obj,args);
}
}经纪公司 经纪公司 = new 经纪公司() { @Override public void 吃饭() { } @Override public void 跳舞() { } @Override public void 唱歌() { } };
代理类实现了所代理的接口,可以在调用代理类方法时调用被代理的对象实现的方法。因此,当使用动态代理时,需要将代理对象转换为被代理对象的接口类型。
原型模式用于创建重复对象 保证性能 这种类型的设计属于创建创建型模式
方式是有一个原型接口
父类实现Cloneable接口
@Override protected Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; }
支持Lambda表达式:是一种特殊的匿名内部类形式,语法更加简洁
允许把函数作为一个方法的参数,将代码像数据一样进行传递
基本语法:
函数式接口 变量名 = (参数,参数)—> {方法体}
注意事项:
形参列表数据类型会自动推断
如果形参列表为空,只需要保留()
如果形参只有一个,()可以省略,只需要参数名即可
如果执行的代码只有一句话且无返回值 { }可省略,
Lambda不会生成一个单独的内部类文件
如果一个接口只有 **一**个 抽象方法 该接口称之为函数式接口
函数式接口可以使用Lambda,lambda表达式会自动匹配到这个抽象方法上
@FunctionalInterface
常见的函数式接口:
Consumer消费型接口
Supplier供给型接口
Function函数型接口
Predicate 断言型接口
方法应用是Lambda表达式的一种简写形式。如果lambda表达式只是调用类已经存在的方法、则可以使用方法引用。
对象::实例方法
类::静态方法
类::实例方法
类::new
//1. 对象::实例方法
Consumer con = s -> System.out.println(s);
con.accept("Hello");
Consumer con2 = System.out::println;
con2.accept("World");
//2. 类::静态方法
/**
* static int compare(int x, int y)
* 比较两个 int数字值。
*/
// Comparator com = (o1,o2)->Integer.compare(o2,o1);
Comparator com2 = Integer::compare;
Set set = new TreeSet<>(com2);
set.add(1);
set.add(2);
set.add(3);
set.add(4);
set.add(5);
set.add(6);
set.add(7);
System.out.println(set);
// 类::实例方法
Function fun = s -> s.getName();
Function fun2 = Student::getName;
//类::new
Supplier sup = () ->new Student();
Supplier sup2 = Student::new;
Student student = sup2.get();
System.out.println(student);
List list = new ArrayList<>();
list.add("宋江");
list.add("卢俊义");
list.add("公孙胜");
list.add("吴用");
list.add("关胜");
list.add("林冲");
//list.forEach(s-> System.out.println(s));
list.forEach(System.out::println);
}
}