为其他对象提供一种代理控制此对象的访问
若一个对象不适合直接引用另一个对象,
代理对象在客户端和目标对象之间起到中介作用
组成:
抽象角色:通过接口 抽象类 真实角色实现了哪些方法
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法
可以附加自己的操作
真实角色:实现抽象角色,定义业务逻辑,供代理角色来调用
代理模式分类
静态代理
动态代理
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 断言型接口
- ackage com.oracle.methodinterface2;
-
- import java.util.*;
- import java.util.function.Consumer;
- import java.util.function.Function;
- import java.util.function.Predicate;
- import java.util.function.Supplier;
-
- /**
- * 四个常见的函数式接口
- * 1. Consumer
消费型接口 表示接受单个输入参数并且不返回结果的操作 - */
- public class MethodInterface {
- public static void main(String[] args) {
- //1. Consumer
消费型接口 - //匿名内部类的方式
- Consumer
consumer = new Consumer() { - @Override
- public void accept(Double money) {
- System.out.println("聚餐消费:" + money);
- }
- };
- happy(consumer, 500);
-
- //Lambda表达式写法
- Consumer
con = money -> System.out.println("聚餐消费:" + money); - happy(con,300);
-
- happy(money -> System.out.println("唱歌消费:" + money),1000);
- happy(money -> System.out.println("洗澡消费" + money),2000);
- happy(money -> System.out.println("足疗消费" + money),3000);
-
-
- Supplier
supplier = new Supplier() { - @Override
- public Integer get() {
- return new Random().nextInt(100);
- }
- };
-
- int[] num = getNum(supplier,10);
- System.out.println(Arrays.toString(num));
-
- int[] num1 = getNum(() -> new Random().nextInt(100),8);
- System.out.println(Arrays.toString(num1));
-
-
- // 3. Function
- String str = handlerStr(s -> s.toUpperCase(), "zhangsan");
- System.out.println(str);
-
- String str2 = handlerStr(s -> s.trim(), " zhang ");
- System.out.println(str2);
-
-
- //4. //4.Predicate
的使用 - List
names = new ArrayList<>(); - names.add("张三丰");
- names.add("张无忌");
- names.add("宋远桥");
- names.add("俞莲舟");
- names.add("俞岱岩");
- names.add("张松溪");
- names.add("张翠山");
- names.add("殷梨亭");
- names.add("莫声谷");
-
- List
list = filterName(s -> s.startsWith("张"), names); - System.out.println(list);
-
-
- }
-
- // 1.Consumer
消费型接口 - public static void happy(Consumer
con, double money) { - con.accept(money);
- }
-
- //2. SUpplier 供给型接口 给方法提供数据
- public static int[] getNum(Supplier
sup,int count){ - int[] arr = new int[count];
- for (int i = 0; i < count; i++) {
- arr[i] = sup.get();
- }
- return arr;
- }
-
- //3. Function
函数式接口 对传入数据进行操作后返回 T 传入的数据, R 返回的数据 - public static String handlerStr(Function
fun,String str) { - return fun.apply(str);
- }
-
- //4.Predicate
断言型接口 判断,返回boolean类型 - public static List
filterName(Predicate pre, List list) { - List
resultList = new ArrayList<>(); - for (String s : list) {
- if(pre.test(s)){
- resultList.add(s);
- }
- }
- return resultList;
- }
-
- }
方法应用是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);
-
- }
- }