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类的相关方法
    }
}

反过来 ,根据类名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());
		}
	}

}

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

已解决,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 表示 必须指明构造方法的参数类型
//注意传入参数是 整数类的包装类和 数组类型的区别

Class类中newInstance()方法参数

  public T newInstance(Object ... initargs)
        throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException
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});
	}

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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. 首先:利用Classl类的 forname方法来获取类
  2. 然后:调用Class类的getConstructor方法来获取构造函数;生成新的实例对象
  3. 其次:调用Class类的getMethod()方法来获取成员对象
  4. 最后:调用Class类的invoke()方法来 执行成员对象
通用方法的调用

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值