本部分 记录和整理 Java设计模式中 经典和常用的部分
常用的 设计模式 分为3大类:创建型模式、行为型模式、结构型模式;
提供一种 在创建对象的同时, 隐藏 创建逻辑的 方式
相比较 使用 new
运算符 来 进行显式创建(直接实例化对象)的方式而言, 更具灵活性;
毕竟在 实际开发中 ,更需要 使得程序 在判断针对 某个给定实例需要 ,半自动化 创建对象
单例模式、简单工厂模式、工厂模式、抽象工厂模式、生成器模式、原型模式
关注 对象之间的 通信;
责任链模式、命令模式、迭代器模式、访问者模式、观察者模式、中介者模式、备忘录模式、状态模式、策略模式、模板方法模式、解释器模式
关注 类和 对象的组合
继承的概念 被用来 组合接口 和 定义组合对象获得 新功能的方式
享元模式、适配器模式、组合模式、代理模式、桥接模式、装饰器模式、外观模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5kY6E89J-1663072490937)(D:\asmr video\Typora 图片资源保存点\5-201123151944949-16308937641331.png)]
首先思考 这几个问题:
基础概念:
- 接口 特征: 仅是 方法定义 和 常量值的 集合,方法没有函数体
- 抽象类特征: 定义 。。。。。
- 二者 都不可以被实例化,继承父类,实现接口
面向对象的编程思想,是 贴近人类 思维的工具。
人类 做事 的 路径便是 : 先 思考 ,再实现, 接口 和 抽象类 便是 思考的 具现化,子类 是 实现的 具现化;
这便是 抽象类 和 接口 存在 和 无法实例化的解释;
作为形而上的 存在;
二者的区别在于 :
思考中 常常分为 顺序问题 和 顺序 +共享问题; 前者 用接口来表示,后者 用 抽象类 来表示;
举例:
这里找 网络上的例子 来阐释
- 何为反射?
Java反射 ( Java Reflection) 在程序运行时获取 已知名称的类 或 对象 相关信息的一种 机制;
包含 类的方法、属性、父类等信息;
常规的程序 设计中 ,调用类对象及 相关方法都是 显式调用的;
public class A{
void func(){}
public static void main(String[] args){
A obj = new A();
obj.func();//显式调用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)
可行的方法:
- 首先通过 Class类的forname方法来获取类
- 然后通过Class类的有参 getContonstor()方法 来获取 对应的构造方法
- 最后调用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});
}
}
使用方法:
- 首先:利用Classl类的 forname方法来获取类
- 然后:调用Class类的getConstructor方法来获取构造函数;生成新的实例对象
- 其次:调用Class类的getMethod()方法来获取成员对象;
- 最后:调用Class类的invoke()方法来 执行成员对象
要知道 类的全路径、方法名字符串、方法参数值;
就可以利用反射机制来执行该方法