Java版事件与委托实现自动创建工厂并热加载

简介: Java版事件与委托实现自动创建工厂并热加载

概念说明

事件与委托

事件是程序中发生的特定动作或状态的通知,可以是用户操作、系统事件或其他触发条件。

委托是一种引用方法的类型,可以将方法作为参数传递、存储和调用。

通过事件与委托的机制,可以实现一种松耦合的方式,使不同的组件之间能够进行通信和交互。

当事件发生时,会调用注册的委托方法来处理事件,从而实现相应的逻辑。

工厂方法

工厂方法是一种创建对象的设计模式,将对象的创建过程封装在一个工厂类中。

工厂方法通过提供一个公共的接口来创建对象,隐藏了具体对象的创建细节。

工厂方法可以根据不同的需求,返回不同的对象实例,提供了一种灵活的对象创建方式。

在Java中,可以使用工厂方法模式来创建对象,例如使用工厂类、抽象工厂接口等。

热加载

热加载是指在应用程序运行期间,动态地替换、添加或删除代码,而无需重启应用程序。

热加载可以提高开发效率,因为不需要每次修改代码后都重新启动应用程序。

在Java中,可以使用工具或框架实现热加载,例如使用JRebel、Spring Boot DevTools等。

需求介绍

 在学习设计模式的时候都接触过事件与委托,也都学习过工厂三兄弟:简单工厂、 工厂方法和抽象工厂。我们就拿工厂方法来说,每个运算类的工厂百分之八十的内容都是一样的。这样就引起了我们通过模板动态的生成工厂类, 想用哪个运算就生成哪个运算对应的工厂然后执行就可以了。实现的方式有很多种,我们今天通过使用事件与委托的形式进行实现,也就是当我们有一个类添加进来之后我们就会触发自动创建工厂的方法。也就相当于我们把自动创建工厂的方法通过委托注册到了事件当中。

代码实现

1.整体结构

b957b15b09f3486d9960e5b6d77f3dee.png

2.工厂方法中已经存在的类

工厂接口

package AutomaticCreateFactoryzhuce;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: FactoryMethod
 * @Author: Administrator
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-03-08 22:36
 * @Version: 1.0
 */
public interface IFactory {
    Operation createOperation();
}

运算类工厂(其他工厂基本上是一样的):目前没有加法类的工厂我们后面会添加加法类工厂然后热加载运行

package AutomaticCreateFactoryzhuce.OperationFactory;
import AutomaticCreateFactoryzhuce.IFactory;
import AutomaticCreateFactoryzhuce.Operation;
import AutomaticCreateFactoryzhuce.OperationSubclass.OperationDiv;
public class DivFactory implements IFactory {
    /**
    * @Author:Wuzilong
    * @Description: 除法运算类
    * @CreateTime: 2023/4/7 8:22
    * @param: 
    * @return: 
    **/
    @Override
    public Operation createOperation() {
        return new OperationDiv();
    }
}

运算父类

package AutomaticCreateFactoryzhuce;
import lombok.Data;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: SimpleFactory
 * @Author: Wuzilong
 * @Description: 运算父类
 * @CreateTime: 2023-03-07 11:12
 * @Version: 1.0
 */
@Data
public class Operation {
    private double numberA=0;
    private  double numberB=0;
    public  double getResult() throws Exception {
        double result=0;
        return result;
    }
}

运算子类

package AutomaticCreateFactoryzhuce.OperationSubclass;
import AutomaticCreateFactoryzhuce.Operation;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: SimpleFactory
 * @Author: Wuzilong
 * @Description: 除法类
 * @CreateTime: 2023-03-07 11:20
 * @Version: 1.0
 */
public class OperationDiv extends Operation {
    @Override
    public  double getResult() throws Exception {
        double result=0;
        result=getNumberA()/getNumberB();
        return result;
    }
}```
## 3.工厂方法之外的其他业务类
### 编译类:将java文件编译成class文件,方便创建出来反射的时候使用
```java
package AutomaticCreateFactoryzhuce;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: AutomaticCreateFactoryV2
 * @Author: Wuzilong
 * @Description: 将java文件编译成class文件
 * @CreateTime: 2023-03-18 22:15
 * @Version: 1.0
 */
public class Compiler extends ClassLoader {
    public void compiler(String compilerPath,String javaPath){
        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
        int status = javac.run(null, null, null, "-d",
                compilerPath,javaPath);
        if(status!=0){
            System.out.println("没有编译成功!");
        }
    }
}

3.工厂方法之外的其他业务类

编译类:将java文件编译成class文件,方便创建出来反射的时候使用

package AutomaticCreateFactoryzhuce;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: AutomaticCreateFactoryV2
 * @Author: Wuzilong
 * @Description: 将java文件编译成class文件
 * @CreateTime: 2023-03-18 22:15
 * @Version: 1.0
 */
public class Compiler extends ClassLoader {
    public void compiler(String compilerPath,String javaPath){
        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
        int status = javac.run(null, null, null, "-d",
                compilerPath,javaPath);
        if(status!=0){
            System.out.println("没有编译成功!");
        }
    }
}

自动创建工厂和客户端类

package AutomaticCreateFactoryzhuce;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: AutomaticCreateFactory
 * @Author: Wuzilong
 * @Description: 自动创建工厂和客户端类
 * @CreateTime: 2023-03-15 16:57
 * @Version: 1.0
 */
public class CreateClass {
    public  void createClass() throws Exception {
        // 工厂文件模板
        String factoryTemplate = "D://项目//设计模式//Java//DesignPattern//src//main//java//AutomaticCreateFactoryzhuce//Template//FactoryTemplate";
        //客户端文件模板
        String clientTemplate ="D://项目//设计模式//Java//DesignPattern//src//main//java//AutomaticCreateFactoryzhuce//Template//ClientTemplate";
        //运算子类的抽象类名
        String className = "FactoryTemplate";
        //运算子类中要实例化的类的抽象类名
        String reClass="OperationClass";
        //客户端的抽象类名
        String clientName="Client";
        //客户端中要实例化的类的抽象类名
        String newName="OperFactory";
        //创建工厂的方法
        createFile(factoryTemplate,className,reClass);
        //创建客户端的方法
        createFile(clientTemplate,clientName,newName);
    }
    public  void createClass(String newClassName) throws Exception {
        // 工厂文件模板
        String factoryTemplate = "D://项目//设计模式//Java//DesignPattern//src//main//java//AutomaticCreateFactoryzhuce//Template//FactoryTemplate";
        //客户端文件模板
        String clientTemplate ="D://项目//设计模式//Java//DesignPattern//src//main//java//AutomaticCreateFactoryzhuce//Template//ClientTemplate";
        //运算子类的抽象类名
        String className = "FactoryTemplate";
        //运算子类中要实例化的类的抽象类名
        String reClass="OperationClass";
        //客户端的抽象类名
        String clientName="Client";
        //客户端中要实例化的类的抽象类名
        String newName="OperFactory";
        //创建工厂的方法
        createFile(factoryTemplate,className,reClass,newClassName);
        //创建客户端的方法
        createFile(clientTemplate,clientName,newName,newClassName);
    }
    private static void createFile(String filePath,String className,String reClass) throws Exception {
        String packagePath="D://项目//设计模式//Java//DesignPattern//src//main//java//AutomaticCreateFactoryzhuce//OperationSubclass//";
        //反射的类路径
        List<String> classPath=new ArrayList();
        //要创建的java类的名字
        List<String> target=new ArrayList<>();
        File file = new File(packagePath);
        //判断是不是文件夹
        if (file.isDirectory()){
            File[] files = file.listFiles();
            for (int i=0; i<files.length;i++){
                String fileNamePath=files[i].getAbsolutePath();
                if (files[i].getAbsolutePath().endsWith(".java")){
                    String operClassPath = fileNamePath.substring(fileNamePath.indexOf("OperationSubclass"), fileNamePath.indexOf(".java"));
                    String createClassName = operClassPath.replace("OperationSubclass\\", "");
                    target.add(createClassName);
                    classPath.add("AutomaticCreateFactoryzhuce.OperationSubclass."+createClassName);
                }
            }
        }
        // 创建java类的存放路径
        String targetURL = "D://项目//设计模式//Java//DesignPattern//src//main//java//AutomaticCreateFactoryzhuce//OperationFactory//";
        //存放class文件的路径
        String classURL="D://项目//设计模式//Java//DesignPattern//target//classes//";
        int isClient=0;
        for (int i = 0; i < target.size(); i++) {
            try {
                BufferedReader bufReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));//数据流读取文件
                //StringBuffer动态的字符串数组
                StringBuffer strBuffer = new StringBuffer();
                //将java编译成class的类
                Compiler compiler = new Compiler();
                //截取计算类的后三位
                String substring = target.get(i).substring(target.get(i).length() - 3);
                String classNameStr=substring+"Factory";
                for (String temp = null; (temp = bufReader.readLine()) != null; temp = null) {
                    //判断当前行是否存在想要替换掉的字符
                    if(temp.contains(className)){
                        if (className.contains("Client")){
                            //替换类名
                            temp = temp.replace(className, classNameStr+"Client");
                        }else{
                            //替换类名
                            temp = temp.replace(className, classNameStr);
                        }
                    }else if(temp.contains(reClass)){
                        if (reClass.contains("Factory")){
                            //替换返回需要实例化的类名
                            temp = temp.replace(reClass, classNameStr);
                            isClient+=1;
                        }else{
                            Class classObject=null;
                            try{
                                classObject = Class.forName(classPath.get(i));
                            }catch (Exception e){
                                compiler.compiler(classURL,packagePath+target.get(i)+".java");
                                classObject = Class.forName(classPath.get(i));
                            }
                            //反射获取计算类的名称
                            //替换返回需要实例化的类名
                            temp=temp.replace(reClass, classObject.getSimpleName());
                        }
                    }
                    //把读取的每一行添加到数组中
                    strBuffer.append(temp);
                    //换行符
                    strBuffer.append(System.getProperty("line.separator"));
                }
                bufReader.close();
                PrintWriter printWriter = null;
                String createClassName=null;
                if (isClient>0){
                    //创建java对象并存放在对应的路径当中
                    printWriter = new PrintWriter(targetURL+classNameStr+"Client"+".java");
                    createClassName=targetURL+ classNameStr+"Client"+".java";
                }else{
                    printWriter = new PrintWriter(targetURL+classNameStr+".java");
                    createClassName=targetURL+ classNameStr+".java";
                }
                //将获取数据的数组写入到创建的java对象中
                printWriter.write(strBuffer.toString().toCharArray());
                printWriter.flush();
                printWriter.close();
                compiler.compiler(classURL,createClassName);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private static void createFile(String filePath,String className,String reClass,String newClassName)  {
        String packagePath="D://项目//设计模式//Java//DesignPattern//src//main//java//AutomaticCreateFactoryzhuce//OperationSubclass//";
        // 创建java类的存放路径
        String targetURL = "D://项目//设计模式//Java//DesignPattern//src//main//java//AutomaticCreateFactoryzhuce//OperationFactory//";
        //存放class文件的路径
        String classURL="D://项目//设计模式//Java//DesignPattern//target//classes//";
        int isClient=0;
            try {
                BufferedReader bufReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));//数据流读取文件
                //StringBuffer动态的字符串数组
                StringBuffer strBuffer = new StringBuffer();
                //将java编译成class的类
                Compiler compiler = new Compiler();
                //截取计算类的后三位
                String substring =newClassName.substring(newClassName.length() - 3);
                String classNameStr=substring+"Factory";
                for (String temp = null; (temp = bufReader.readLine()) != null; temp = null) {
                    //判断当前行是否存在想要替换掉的字符
                    if(temp.contains(className)){
                        if (className.contains("Client")){
                            //替换类名
                            temp = temp.replace(className, classNameStr+"Client");
                        }else{
                            //替换类名
                            temp = temp.replace(className, classNameStr);
                        }
                    }else if(temp.contains(reClass)){
                        if (reClass.contains("Factory")){
                            //替换返回需要实例化的类名
                            temp = temp.replace(reClass, classNameStr);
                            isClient+=1;
                        }else{
                            newClassName=newClassName.replace("//",".");
                            Class classObject=null;
                            try{
                                classObject = Class.forName(newClassName);//新创建出来的类的相对路径
                            }catch (Exception e){
                                compiler.compiler(classURL,packagePath+newClassName+".java");
                                classObject = Class.forName(newClassName);
                            }
                            //反射获取计算类的名称
                            //替换返回需要实例化的类名
                            temp=temp.replace(reClass, classObject.getSimpleName());
                        }
                    }
                    //把读取的每一行添加到数组中
                    strBuffer.append(temp);
                    //换行符
                    strBuffer.append(System.getProperty("line.separator"));
                }
                bufReader.close();
                PrintWriter printWriter = null;
                String createClassName=null;
                if (isClient>0){
                    //创建java对象并存放在对应的路径当中
                    printWriter = new PrintWriter(targetURL+classNameStr+"Client"+".java");
                    createClassName=targetURL+ classNameStr+"Client"+".java";
                }else{
                    printWriter = new PrintWriter(targetURL+classNameStr+".java");
                    createClassName=targetURL+ classNameStr+".java";
                }
                //将获取数据的数组写入到创建的java对象中
                printWriter.write(strBuffer.toString().toCharArray());
                printWriter.flush();
                printWriter.close();
                compiler.compiler(classURL,createClassName);
            } catch (Exception e) {
                e.printStackTrace();
            }
    }
}

创建类的模板:当前使用的是txt文件,也可以使用其他文件例如mv等

运算子类

package AutomaticCreateFactoryzhuce.OperationFactory;
import AutomaticCreateFactoryzhuce.IFactory;
import AutomaticCreateFactoryzhuce.Operation;
import AutomaticCreateFactoryzhuce.OperationSubclass.OperationClass;
public class FactoryTemplate implements IFactory {
    @Override
    public Operation createOperation() {
        return new OperationClass();
    }

每个运算类对应的客户端模板

package AutomaticCreateFactoryzhuce.OperationFactory;
import AutomaticCreateFactoryzhuce.IFactory;
import AutomaticCreateFactoryzhuce.Operation;
import AutomaticCreateFactoryzhuce.OperationFactory.OperFactory;
public class Client {
    public  void createMethod() throws Exception {
        IFactory operFactory=new OperFactory();
        Operation operation = operFactory.createOperation();
        operation.setNumberA(3);
        operation.setNumberB(2);
        double result=operation.getResult();
        System.out.println("自动生成工厂方法的运行结果:"+result);
    }
}

监听类

package AutomaticCreateFactoryzhuce;
import java.nio.file.*;
import java.util.EventListener;
import java.util.EventObject;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: AutomaticCreateFactoryzhuce
 * @Author: Wuzilong
 * @Description: 监听是否有新的类
 * @CreateTime: 2023-03-27 09:29
 * @Version: 1.0
 */
public class Listener  {
    public void run() {
        WatchKey key;
        try {
            String path = "D://项目//设计模式//Java//DesignPattern//src//main//java//AutomaticCreateFactoryzhuce//OperationSubclass//";
            //创建一个watchservice对象,用于监听目录事件
            WatchService watchservice = FileSystems.getDefault().newWatchService();
            //监控目录下是否有创建的文件
            Paths.get(path).register(watchservice, StandardWatchEventKinds.ENTRY_CREATE);
            while (true) {
                key = watchservice.take();//没有文件增加时,阻塞在这里
                //key.pollEvents()用于获取文件变化事件
                for (WatchEvent<?> event : key.pollEvents()) {
                    //返回触发事件的文件或目录的路径(相对路径)
                    String filename = path  + event.context();
                    System.out.println("增加文件的文件夹路径" + filename);
                    String newClassName = filename.substring(filename.indexOf("AutomaticCreateFactoryzhuce"), filename.indexOf(".java"));
                    Event eventObject = new Event();
                    eventObject.addDelegate(new Delegate(new CreateClass(),"createClass",newClassName));
                    eventObject.addClass();
                }
                if (!key.reset()) {
                    break; //中断循环
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

委托类

package AutomaticCreateFactoryzhuce;
import java.lang.reflect.Method;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: AutomaticCreateFactoryzhuce
 * @Author: Wuzilong
 * @Description: 委托类
 * @CreateTime: 2023-03-29 08:48
 * @Version: 1.0
 */
public class Delegate {
    private Object obj;
    private String methodName;
    private Object[] methodParameter;
    private Class<?>[] methodType;
    public Delegate(Object obj, String methodName, Object... methodParameter) {
        this.obj = obj;
        this.methodName = methodName;
        this.methodParameter = methodParameter;
        int len = methodParameter.length;
        this.methodType = new Class[len];
        for (int i = 0; i < len; i++) {
            methodType[i] = methodParameter[i].getClass();
        }
    }
    public void eventHandler() throws Exception {
        Method method = obj.getClass().getDeclaredMethod(methodName, methodType);
        method.invoke(obj, methodParameter);
    }
}

事件类

package AutomaticCreateFactoryzhuce;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: AutomaticCreateFactoryzhuce
 * @Author: Wuzilong
 * @Description: 事件类
 * @CreateTime: 2023-03-27 09:40
 * @Version: 1.0
 */
public class Event  {
    private List<Delegate> objects=new ArrayList<>();
    public void addDelegate(Delegate source) {
        objects.add(source);
    }
    public void addClass() throws Exception {
        if (objects.size()!=0){
            for (Delegate object:objects){
                object.eventHandler();
            }
        }
    }
}

两个线程类,一个只负责监听有没有新类的加入,一个只负责让用户输入运算

监听线程

package AutomaticCreateFactoryzhuce;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: AutomaticCreateFactory
 * @Author: Wuzilong
 * @Description: 触发监听的线程
 * @CreateTime: 2023-03-21 08:31
 * @Version: 1.0
 */
public class RegularService implements Runnable{
    public void run() {
        CreateClass createClass=new CreateClass();
        Listener listener = new Listener();
        // 需要定时执行的任务
        Runnable runnable = () -> {
            try {
                createClass.createClass();
                listener.run();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
        ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
        //立即执行,并且每5秒执行一次
        ses.scheduleAtFixedRate(runnable, 0, 10000, TimeUnit.MILLISECONDS);
    }
}

用户输入运算线程

package AutomaticCreateFactoryzhuce;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
 * @BelongsProject: DesignPattern
 * @BelongsPackage: AutomaticCreateFactoryzhuce
 * @Author: Wuzilong
 * @Description: 定时触发用户想要的运算
 * @CreateTime: 2023-03-27 21:14
 * @Version: 1.0
 */
public class RegularClient {
    public void run() {
        // 需要定时执行的任务
        Runnable runnable = () -> {
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                System.out.println("请输入要执行的算法工厂");
                String operation = br.readLine();
                Class aClass = Class.forName("AutomaticCreateFactoryzhuce.OperationFactory." + operation + "Client");
                Object object = aClass.newInstance();
                Method mainMethod = aClass.getMethod("createMethod");
                mainMethod.invoke(object);
            } catch (Exception e) {
                System.out.println("暂不支持该运算");
            }
        };
        ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
        //立即执行,并且每5秒执行一次
        ses.scheduleAtFixedRate(runnable, 0, 8000, TimeUnit.MILLISECONDS);
    }
}

4.运行结果

87e0334aabe7424cb4d4643a97d69f8e.png6ddc3ffd4fcd40549c675e2a4818b560.png

总结提升

 只要我们把最基础的内容学会了其他的内容就是我们通过基础的内容组合而成的。实现这个例子的时候一开始觉得实现起来比较困难。但是把整个过程拆分一下,都是之前学习过的内容:反射、事件与委托、工厂方法等。对于一个比较大的任务颗粒化就十分的重要。把每个小的颗粒逐个击破大问题也就没有了。


相关文章
|
26天前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
2月前
|
Java C#
Java的监听处理事件--小球移动案例
Java的监听处理事件--小球移动案例
19 0
|
5月前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
70 1
|
5月前
|
Java Spring
如何在Java中实现事件驱动编程?
如何在Java中实现事件驱动编程?
|
6月前
|
存储 Java API
Java中的CQRS和事件溯源模式解析
Java中的CQRS和事件溯源模式解析
|
5月前
|
设计模式 存储 缓存
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
Java面试题:结合建造者模式与内存优化,设计一个可扩展的高性能对象创建框架?利用多线程工具类与并发框架,实现一个高并发的分布式任务调度系统?设计一个高性能的实时事件通知系统
65 0
|
5月前
|
设计模式 存储 缓存
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
45 0
|
5月前
|
Java UED
Java中的事件驱动编程模型
Java中的事件驱动编程模型
|
7月前
|
设计模式 消息中间件 Java
Java观察者模式:实现松耦合的事件通知机制
Java观察者模式:实现松耦合的事件通知机制
73 2
|
7月前
|
Java UED
Java中的事件处理机制
Java中的事件处理机制
148 1