• Java设计模式01- 概览


    Java设计模式



    前言:

    本部分 记录和整理 Java设计模式中 经典和常用的部分

    Java面向对象的设计原则


    • 接口编程,而非 对实现编程
    • 优先使用对象组合 ,而非 继承

    常用的 设计模式 分为3大类:创建型模式、行为型模式、结构型模式;

    创建型模式


    提供一种 在创建对象的同时, 隐藏 创建逻辑的 方式

    相比较 使用 new 运算符 来 进行显式创建(直接实例化对象)的方式而言, 更具灵活性;

    毕竟在 实际开发中 ,更需要 使得程序 在判断针对 某个给定实例需要 ,半自动化 创建对象

    单例模式、简单工厂模式、工厂模式、抽象工厂模式、生成器模式、原型模式

    行为型模式


    关注 对象之间的 通信;

    责任链模式、命令模式、迭代器模式、访问者模式、观察者模式、中介者模式、备忘录模式、状态模式、策略模式、模板方法模式、解释器模式

    结构型模式


    关注 类和 对象的组合

    继承的概念 被用来 组合接口 和 定义组合对象获得 新功能的方式

    享元模式、适配器模式、组合模式、代理模式、桥接模式、装饰器模式、外观模式

    预备知识


    1. 算法 和 数据结构部分
    2. 接口、抽象类 和 反射的 基础知识

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5kY6E89J-1663072490937)(D:\asmr video\Typora 图片资源保存点\5-201123151944949-16308937641331.png)]

    接口和 抽象类


    首先思考 这几个问题:

    1. 接口 中能定义 抽象方法,为何 还需要抽象类?
    2. 抽象方法中没有结构体,不能实例化,说明 接口、抽象类 本身是没有用途的 ,为何还存在?
    3. 抽象类 和 接口 的关系是?

    基础概念:

    1. 接口 特征: 仅是 方法定义 和 常量值的 集合,方法没有函数体
    2. 抽象类特征: 定义 。。。。。
    3. 二者 都不可以被实例化,继承父类,实现接口

    面向对象的编程思想,是 贴近人类 思维的工具。

    人类 做事 的 路径便是 : 先 思考 ,再实现, 接口 和 抽象类 便是 思考的 具现化,子类 是 实现的 具现化;

    这便是 抽象类 和 接口 存在 和 无法实例化的解释;

    作为形而上的 存在;

    二者的区别在于 :

    思考中 常常分为 顺序问题 和 顺序 +共享问题; 前者 用接口来表示,后者 用 抽象类 来表示;

    举例:

    这里找 网络上的例子 来阐释

    反射


    1. 何为反射?

    Java反射 ( Java Reflection) 在程序运行时获取 已知名称的类 或 对象 相关信息的一种 机制;

    包含 类的方法、属性、父类等信息;

    常规的程序 设计中 ,调用类对象及 相关方法都是 显式调用的;

    public class A{
        void func(){}
        public static void main(String[] args){
            A obj = new A();
            obj.func();//显式调用A类的相关方法
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    反过来 ,根据类名A

    • 列出 A类中 哪些属性 和 方法
    • 对任意一个对象, 调用它 的任意一个方法,

    在JDK 中 , 通过 java.lang.reflect包中 4个类来实现

    • Class 类: 代表一个类
    • Constructor类: 代表类的构造方法
    • Field类:代表 类的成员变量
    • Method类: 代表类的方法

    运用 上述 4 个类及相关方法,就能够 解析 无穷多的系统类 和 自定义类结构、创建对象、方法执行等功能,使用形式统一的

    统一形式 解析类的构造方法、成员变量、成员方法

    package reflect;
    import java.lang.reflect.*;
    public class ClassInfoDemo {
    		int m;//成员变量
    		String str;
    		float f;
    		// 默认构造方法
    		public ClassInfoDemo() {}
    		//自定义的构造方案
    		public ClassInfoDemo(int m) {}
    		//成员方法 func1,func2
    		private void func1() {
    			
    		}
    		private void func2() {
    			
    		}
    	@SuppressWarnings("unused")
    	public static void main(String[] args)throws Exception {
    		// TODO 自动生成的方法存根
    		//加载并初始化 指定的类ClassInfoDemo
    		Class ClassInfo = Class.forName("reflect.ClassInfoDemo");
    		
    		System.out.println("类ClassInfoDemo构造函数如下所示:");
    		//获取类ClassInfoDemo的构造函数
    		Constructor cons[] = ClassInfo.getConstructors();
    		for (int i = 0;i < cons.length;i++) {
    			System.out.println(cons[i].toString());
    		}
    		System.out.println();
    		//获取类ClassInfoDemo中的所有变量 
    		System.out.println("类ClassInfoDemo的变量如下所示:");
    		Field fields[] = ClassInfo.getDeclaredFields();
    		for(int i = 0; i < fields.length;i++) {
    			System.out.println(fields[i].toString());
    		}
    		System.out.println();
    		//获取类的所有方法
    		System.out.println("类ClassInfoDemo的方法如下所示:");
    		Method methods[] = ClassInfo.getDeclaredMethods();
    		for(int i = 0; i < methods.length; i++) {
    			System.out.println(methods[i].toString());
    		}
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    这里 出现一个问题 : 一直找不到主类,暂时搁置

    已解决,Bug在于 没有写明 要反射的类的全路径,同时,反射机制在 同一个类中是没有意义的;

    运行截图如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qRRdOavJ-1663072490939)(D:/asmr%20video/Typora%20%E5%9B%BE%E7%89%87%E8%B5%84%E6%BA%90%E4%BF%9D%E5%AD%98%E7%82%B9/image-20210511132804117.png)]

    统一形式 调用类的构造方法

    案例参照 Java-Design-Patterns项目中 reflect.ClassConstructorDemo(2)

    可行的方法:

    1. 首先通过 Class类的forname方法来获取类
    2. 然后通过Class类的有参 getContonstor()方法 来获取 对应的构造方法
    3. 最后调用Class类的newInstance()方法,完成该实例的创建
    方法参数的理解

    Class 类中getConstrucotor()方法参数:

     public Constructor<T> getConstructor(Class<?>... parameterTypes)
            throws NoSuchMethodException, SecurityException {
            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
            return getConstructor0(parameterTypes, Member.PUBLIC);
        }
    //parameterTypes 表示 必须指明构造方法的参数类型
    //注意传入参数是 整数类的包装类和 数组类型的区别
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Class类中newInstance()方法参数

      public T newInstance(Object ... initargs)
            throws InstantiationException, IllegalAccessException,
                   IllegalArgumentException, InvocationTargetException
    
    • 1
    • 2
    • 3
    package reflect;
    import java.lang.reflect.*;
    public class ClassConstructorDemo {
    	
    	public ClassConstructorDemo() {
    		System.out.println("This is A:");
    		// TODO 自动生成的构造函数存根
    	}
    
    
    	public ClassConstructorDemo(Integer m) {
    		System.out.println("This is A:"+m);
    		// TODO 自动生成的构造函数存根
    	}
    	
    	
    	public ClassConstructorDemo(String str,Integer m) {
    		System.out.println("This is A:"+str+":"+m);
    		// TODO 自动生成的构造函数存根
    	}
    
    
    	public static void main(String[] args) throws Exception{
    		// TODO 自动生成的方法存根
    		Class classInfo = Class.forName("reflect.ClassConstructorDemo");
    		
    		System.out.println("---------------------- 第一种方法------------------------------------");
    		/**
    		 * 
    		 */
    	/*	
    		Constructor cons[] = classInfo.getConstructors();
    		//调用无参数构造函数
    		cons[0].newInstance();
    		//
    		cons[1].newInstance(new Object[] {10});
    		//
    		cons[2].newInstance(new Object[] {"Hello",2010});
    		*/
    		System.out.println("---------------------- 第二种方法------------------------------------");
    		/**
    		 * 
    		 */
    		Constructor c = classInfo.getConstructor();
    		c.newInstance();
    		
    		//
    		c=classInfo.getConstructor(new Class[] {Integer.class});
    		c.newInstance(new Object[] {10});
    		
    		//
    		c = classInfo.getConstructor(new Class[] {String.class,Integer.class});
    		c.newInstance(new Object[] {"Hello",2010});
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ppcjx1Qw-1663072490940)(D:/asmr%20video/Typora%20%E5%9B%BE%E7%89%87%E8%B5%84%E6%BA%90%E4%BF%9D%E5%AD%98%E7%82%B9/image-20210511155440733.png)]

    案例查看 ClassConstructorDemo02, 测试的类是 Person;

    借助这个案例,仔细分析 使用getConstructor()方法 的使用细则;

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ch07WlZo-1663072490940)(D:/asmr%20video/Typora%20%E5%9B%BE%E7%89%87%E8%B5%84%E6%BA%90%E4%BF%9D%E5%AD%98%E7%82%B9/image-20210511162137590.png)]

    统一形式 调用成员方法


    package reflect;
    import java.lang.reflect.*;
    public class ClassMethodDemo {
    	public void func1(){
    		System.out.println("This is func1: ");
    	}
    	public void func2(Integer m){
    		System.out.println("This is func2: ");
    	}
    	public void func3(String str,Integer m){
    		System.out.println("This is func3: ");
    	}
    	@SuppressWarnings({ "unchecked", "rawtypes" })
    	public static void main(String[] args)throws Exception {
    		// TODO 自动生成的方法存根
    		Class classInfo = Class.forName("reflect.ClassMethodDemo");
    		//调用无参数构造函数,生成新的实例对象
    		Object obj = classInfo.getConstructor().newInstance();
    		
    		//调用无参成员函数func1
    		Method mt1 = classInfo.getMethod("func1",null);
    		mt1.invoke(obj);
    		//调用第1个 参数成员函数func2
    		Method mt2 = classInfo.getMethod("func2", Integer.class);
    		mt2.invoke(obj, new Object[] {10});
    		//调用第2个 参数成员函数func3
    		Method mt3 = classInfo.getMethod("func3", String.class,Integer.class);
    		mt3.invoke(obj, new Object[] {"Hello",2010});
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    使用方法:

    1. 首先:利用Classl类的 forname方法来获取类
    2. 然后:调用Class类的getConstructor方法来获取构造函数;生成新的实例对象
    3. 其次:调用Class类的getMethod()方法来获取成员对象
    4. 最后:调用Class类的invoke()方法来 执行成员对象
    通用方法的调用

    要知道 类的全路径、方法名字符串、方法参数值;

    就可以利用反射机制来执行该方法

  • 相关阅读:
    玩全栈,做自己喜欢做的事,写自己喜欢写的代码
    算法训练 第六周
    android自定义View: 绘制图表(一)
    Redis的五种常用数据类型
    [游戏开发]Unity SRP 学习(一)
    Python的第三方日志库Loguru
    图解快速排序算法
    Java 创建线程的方法
    网络爬虫是什么?怎么学python爬虫
    python教程:一定要会的-类的定义
  • 原文地址:https://blog.csdn.net/myxk_/article/details/126841188