• day40 设计模式、jdk8新特性


    一、代理模式

    为其他对象提供一种代理控制此对象的访问

    若一个对象不适合直接引用另一个对象,

    代理对象在客户端和目标对象之间起到中介作用

    组成:

    抽象角色:通过接口 抽象类 真实角色实现了哪些方法

    代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法

    可以附加自己的操作

    真实角色:实现抽象角色,定义业务逻辑,供代理角色来调用

    1. 代理模式分类

      • 静态代理

      • 动态代理

        • JDK动态代理

        • cglib动态代理

    2. 静态代理: 抽象角色固定, 代理角色和代理的真实角色是固定。

    3. 动态代理

      通过反射机制来实现的,代理角色不在是固定的角色,而是一个通用的工具类,还可以代理很多操作

    动态代理是在静态代理的基础上,代理的真实角色由设置好的固定的一个变成自由的多个,实现更广泛的应用。

    动态代理的代理角色类Proxyutil需要实现接口InvocationHandler

    1. public class ProxyUtil经纪人 implements InvocationHandler {
    2. private Object obj;
    3. public Object newProxyInstance(Object obj){
    4. this.obj = obj;
    5. return Proxy.newProxyInstance(this.obj.getClass().getClassLoader(),
    6. obj.getClass().getInterfaces(),
    7. this);
    8. };
    9. @Override
    10. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    11. return method.invoke(obj,args);
    12. }
    13. }

    /**
     * 代理角色:
     */
    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);
        }
    }

    1. 经纪公司 经纪公司 = new 经纪公司() {
    2. @Override
    3. public void 吃饭() {
    4. }
    5. @Override
    6. public void 跳舞() {
    7. }
    8. @Override
    9. public void 唱歌() {
    10. }
    11. };

    代理类实现了所代理的接口,可以在调用代理类方法时调用被代理的对象实现的方法。因此,当使用动态代理时,需要将代理对象转换为被代理对象的接口类型。

    二、原型模式

    原型模式用于创建重复对象 保证性能  这种类型的设计属于创建创建型模式

    方式是有一个原型接口

    父类实现Cloneable接口 

    1. @Override
    2. protected Object clone() {
    3. Object clone = null;
    4. try {
    5. clone = super.clone();
    6. } catch (CloneNotSupportedException e) {
    7. e.printStackTrace();
    8. }
    9. return clone;
    10. }

    三、JDK8新特性

    支持Lambda表达式:是一种特殊的匿名内部类形式,语法更加简洁

    允许把函数作为一个方法的参数,将代码像数据一样进行传递

    基本语法:

    函数式接口 变量名 =  (参数,参数)—> {方法体}

    注意事项:

    形参列表数据类型会自动推断

    如果形参列表为空,只需要保留()

    如果形参只有一个,()可以省略,只需要参数名即可

    如果执行的代码只有一句话且无返回值 { }可省略,

    Lambda不会生成一个单独的内部类文件

    四、函数式接口

    如果一个接口只有  **一**个 抽象方法 该接口称之为函数式接口

    函数式接口可以使用Lambda,lambda表达式会自动匹配到这个抽象方法上

    @FunctionalInterface

    常见的函数式接口:
    

    Consumer消费型接口

    Supplier供给型接口

    Function函数型接口

    Predicate 断言型接口

    1. ackage com.oracle.methodinterface2;
    2. import java.util.*;
    3. import java.util.function.Consumer;
    4. import java.util.function.Function;
    5. import java.util.function.Predicate;
    6. import java.util.function.Supplier;
    7. /**
    8. * 四个常见的函数式接口
    9. * 1. Consumer 消费型接口 表示接受单个输入参数并且不返回结果的操作
    10. */
    11. public class MethodInterface {
    12. public static void main(String[] args) {
    13. //1. Consumer 消费型接口
    14. //匿名内部类的方式
    15. Consumer consumer = new Consumer() {
    16. @Override
    17. public void accept(Double money) {
    18. System.out.println("聚餐消费:" + money);
    19. }
    20. };
    21. happy(consumer, 500);
    22. //Lambda表达式写法
    23. Consumer con = money -> System.out.println("聚餐消费:" + money);
    24. happy(con,300);
    25. happy(money -> System.out.println("唱歌消费:" + money),1000);
    26. happy(money -> System.out.println("洗澡消费" + money),2000);
    27. happy(money -> System.out.println("足疗消费" + money),3000);
    28. Supplier supplier = new Supplier() {
    29. @Override
    30. public Integer get() {
    31. return new Random().nextInt(100);
    32. }
    33. };
    34. int[] num = getNum(supplier,10);
    35. System.out.println(Arrays.toString(num));
    36. int[] num1 = getNum(() -> new Random().nextInt(100),8);
    37. System.out.println(Arrays.toString(num1));
    38. // 3. Function
    39. String str = handlerStr(s -> s.toUpperCase(), "zhangsan");
    40. System.out.println(str);
    41. String str2 = handlerStr(s -> s.trim(), " zhang ");
    42. System.out.println(str2);
    43. //4. //4.Predicate 的使用
    44. List names = new ArrayList<>();
    45. names.add("张三丰");
    46. names.add("张无忌");
    47. names.add("宋远桥");
    48. names.add("俞莲舟");
    49. names.add("俞岱岩");
    50. names.add("张松溪");
    51. names.add("张翠山");
    52. names.add("殷梨亭");
    53. names.add("莫声谷");
    54. List list = filterName(s -> s.startsWith("张"), names);
    55. System.out.println(list);
    56. }
    57. // 1.Consumer 消费型接口
    58. public static void happy(Consumer con, double money) {
    59. con.accept(money);
    60. }
    61. //2. SUpplier 供给型接口 给方法提供数据
    62. public static int[] getNum(Suppliersup,int count){
    63. int[] arr = new int[count];
    64. for (int i = 0; i < count; i++) {
    65. arr[i] = sup.get();
    66. }
    67. return arr;
    68. }
    69. //3. Function 函数式接口 对传入数据进行操作后返回 T 传入的数据, R 返回的数据
    70. public static String handlerStr(Function fun,String str){
    71. return fun.apply(str);
    72. }
    73. //4.Predicate 断言型接口 判断,返回boolean类型
    74. public static List filterName(Predicate pre, List list){
    75. List resultList = new ArrayList<>();
    76. for (String s : list) {
    77. if(pre.test(s)){
    78. resultList.add(s);
    79. }
    80. }
    81. return resultList;
    82. }
    83. }

    五、方法引用

    方法应用是Lambda表达式的一种简写形式。如果lambda表达式只是调用类已经存在的方法、则可以使用方法引用。

    对象::实例方法

     类::静态方法

    类::实例方法

    类::new

    1. //1. 对象::实例方法
    2. Consumer con = s -> System.out.println(s);
    3. con.accept("Hello");
    4. Consumer con2 = System.out::println;
    5. con2.accept("World");
    6. //2. 类::静态方法
    7. /**
    8. * static int compare(int x, int y)
    9. * 比较两个 int数字值。
    10. */
    11. // Comparator com = (o1,o2)->Integer.compare(o2,o1);
    12. Comparator com2 = Integer::compare;
    13. Set set = new TreeSet<>(com2);
    14. set.add(1);
    15. set.add(2);
    16. set.add(3);
    17. set.add(4);
    18. set.add(5);
    19. set.add(6);
    20. set.add(7);
    21. System.out.println(set);
    22. // 类::实例方法
    23. Function fun = s -> s.getName();
    24. Function fun2 = Student::getName;
    25. //类::new
    26. Supplier sup = () ->new Student();
    27. Supplier sup2 = Student::new;
    28. Student student = sup2.get();
    29. System.out.println(student);
    30. List list = new ArrayList<>();
    31. list.add("宋江");
    32. list.add("卢俊义");
    33. list.add("公孙胜");
    34. list.add("吴用");
    35. list.add("关胜");
    36. list.add("林冲");
    37. //list.forEach(s-> System.out.println(s));
    38. list.forEach(System.out::println);
    39. }
    40. }

  • 相关阅读:
    StyleLint入门配置
    okcc坐席进线太慢,怎么办?
    千峰商城-springboot项目搭建-82-订单提交及支付-支付回调
    QListWidget 类使用教程
    galeracluster高可用集群异常恢复
    专题 递归与递推
    一、八大排序(sort)
    C#的基本知识(1)
    栈的实现(c语言)
    python内置函数+lambda函数
  • 原文地址:https://blog.csdn.net/weixin_45939821/article/details/132869096