一、代理模式
为其他对象提供一种代理控制此对象的访问
若一个对象不适合直接引用另一个对象,
代理对象在客户端和目标对象之间起到中介作用
组成:
抽象角色:通过接口 抽象类 真实角色实现了哪些方法
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法
可以附加自己的操作
真实角色:实现抽象角色,定义业务逻辑,供代理角色来调用
-
代理模式分类
-
静态代理
-
动态代理
-
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);};@Overridepublic 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 经纪公司() {@Overridepublic void 吃饭() {}@Overridepublic void 跳舞() {}@Overridepublic void 唱歌() {}};
代理类实现了所代理的接口,可以在调用代理类方法时调用被代理的对象实现的方法。因此,当使用动态代理时,需要将代理对象转换为被代理对象的接口类型。
二、原型模式
原型模式用于创建重复对象 保证性能 这种类型的设计属于创建创建型模式
方式是有一个原型接口
父类实现Cloneable接口
@Overrideprotected Object clone() {Object clone = null;try {clone = super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return clone;}
三、JDK8新特性
支持Lambda表达式:是一种特殊的匿名内部类形式,语法更加简洁
允许把函数作为一个方法的参数,将代码像数据一样进行传递
基本语法:
函数式接口 变量名 = (参数,参数)—> {方法体}
注意事项:
形参列表数据类型会自动推断
如果形参列表为空,只需要保留()
如果形参只有一个,()可以省略,只需要参数名即可
如果执行的代码只有一句话且无返回值 { }可省略,
Lambda不会生成一个单独的内部类文件
四、函数式接口
如果一个接口只有 **一**个 抽象方法 该接口称之为函数式接口
函数式接口可以使用Lambda,lambda表达式会自动匹配到这个抽象方法上
@FunctionalInterface
常见的函数式接口:
Consumer消费型接口
Supplier供给型接口
Function函数型接口
Predicate 断言型接口
五、方法引用
方法应用是Lambda表达式的一种简写形式。如果lambda表达式只是调用类已经存在的方法、
对象::实例方法
类::静态方法
类::实例方法
类::new
//1. 对象::实例方法Consumer<String> con = s -> System.out.println(s);con.accept("Hello");Consumer<String> con2 = System.out::println;con2.accept("World");//2. 类::静态方法/*** static int compare(int x, int y)* 比较两个 int数字值。*/// Comparator<Integer> com = (o1,o2)->Integer.compare(o2,o1);Comparator<Integer> com2 = Integer::compare;Set<Integer> 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<Student,String> fun = s -> s.getName();Function<Student,String> fun2 = Student::getName;//类::newSupplier<Student> sup = () ->new Student();Supplier<Student> sup2 = Student::new;Student student = sup2.get();System.out.println(student);List<String> 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);}
}