一、背景介绍
工厂方法仅仅为了解决简单工厂判断不符合开闭原则的问题?
工厂方法仅仅为了解决业务子类实例化的问题?
然而我的观点是工厂方法是为了解决自动化创建对象的问题;如何理解这句话?请读者朋友继续往下看。
阅读这篇文章您会了解到小编在进行设计模式学习过程中的思路、总结以及产生的问题,希望能够和读者碰撞出更多的"车祸"。
二、学习思路
1.绘制模式的UML图
2.根据UML图编写代码
3.寻找模式的例子进行UML图的绘制
4.根据例子的UML图编写代码
5.对比两个模式的区别,以及分别的作用与意义
6.请教高人
三、学习过程
1.实现绘制UML以及实现代码下面是对于工厂方法的UML图
2.开始解答以上的问题
2.1.工厂方法仅仅为了解决简单工厂判断不符合开闭原则的问题?
答:如果不用工厂方法,简单工厂对应的实现在客户端直接实例化不同的子类即可;依然能解决开闭原则的问题
2.2.工厂方法仅仅为了解决业务子类实例化的问题?
答:业务子类实例化,交由客户端通过反射直接获取子类即可
2.3.然而我的观点是工厂方法是为了解决自动化的问题
答:有了工厂方法这个理念我就可以自动将业务子类一一对应进行实例化,如果我的子类成千上万的话;并且我的子类需要动态的扩充的话如何通过自动化来实现?
下面我会介绍如何自动实现业务子类的实例化
3.自动实现业务子类的实例化内容
package com.mark.b01Operation.service.impl;
import com.mark.b01Operation.service.CreateClassService;
import com.mark.b01Operation.service.operation.AbstractOperation;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.Arrays;
@Service
public class CreateClassServiceImpl implements CreateClassService {
@Resource
private ConfigurableListableBeanFactory configurableListableBeanFactory;
@Resource
private AbstractBeanFactory abstractBeanFactory;
@Override
public void CreateClass(String str,String name) throws Exception {
//1.获取java编程语言编译器
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//2.获取文件管理器
StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);
//3.获取class文件管理器
ClassJavaFileManager classJavaFileManager = new ClassJavaFileManager(standardFileManager);
//4.获取要加载的.java文件内容
StringObject stringObject = new StringObject(new URI(name+".java"), JavaFileObject.Kind.SOURCE, str);
//5.调用编译器,传入参数获取要执行的编译任务
JavaCompiler.CompilationTask task = compiler.getTask(null, classJavaFileManager,
null, null, null, Arrays.asList(stringObject));
//6.执行编译任务
if (task.call()) {
//7.获取类文件获取.class文件
ClassJavaFileObject javaFileObject = classJavaFileManager.getClassJavaFileObject();
//8.创建类加载器,并将.class文件传入
ClassLoader classLoader = new MyClassLoader(javaFileObject);
//9.获得该类的实例
Object AddFactory = classLoader.loadClass(name).newInstance();
//10.调用spring管理bean的集合,将实例化的类交给spring管理
configurableListableBeanFactory.registerSingleton(name,AddFactory);
//11.通过spring的BeanFactory获取bean验证是否可以获取到
AbstractOperation abstractOperation = (AbstractOperation) abstractBeanFactory.getBean(name);
System.out.println(AddFactory);
}
}
/**
*自定义fileManager 继承ForwardingJavaFileManager文件管理器
*/
static class ClassJavaFileManager extends ForwardingJavaFileManager {
private ClassJavaFileObject classJavaFileObject;
public ClassJavaFileManager(JavaFileManager fileManager) {
super(fileManager);
}
public ClassJavaFileObject getClassJavaFileObject() {
return classJavaFileObject;
}
//这个方法一定要自定义
//获取输出的文件对象,它表示给定位置处指定类型的制定类
@Override
public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
return (classJavaFileObject = new ClassJavaFileObject(className,kind));
}
}
/**
* 存储源文件 SimpleJavaFileObject:简单的java文件对象
*/
static class StringObject extends SimpleJavaFileObject {
private String content;
public StringObject(URI uri, Kind kind, String content) {
super(uri, kind);
this.content = content;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return this.content;
}
}
/**
* class文件(不需要存到文件中)
*/
static class ClassJavaFileObject extends SimpleJavaFileObject{
ByteArrayOutputStream outputStream;
public ClassJavaFileObject(String className, Kind kind) {
super(URI.create(className + kind.extension), kind);
this.outputStream = new ByteArrayOutputStream();
}
//这个也要实现
@Override
public OutputStream openOutputStream() throws IOException {
return this.outputStream;
}
public byte[] getBytes(){
return this.outputStream.toByteArray();
}
}
//自定义classloader
static class MyClassLoader extends ClassLoader{
private ClassJavaFileObject classJavaFileObject;
public MyClassLoader(ClassJavaFileObject classJavaFileObject){
this.classJavaFileObject = classJavaFileObject;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = this.classJavaFileObject.getBytes();
return defineClass(name,bytes,0,bytes.length);
}
}
}
扩展:spring中最核心的BeanFactory就是通过工厂方法+注解来实现的对于业务类实例化操作
四、学习总结
收获:
对于工厂方法的认识有了质的变化,对于后续其它模式的学习指明了方向。
提出的问题:
在研究spring工厂的过程中了解到注解扫描类默认为单例,为什么?
五、升华
高人指路之后要多问一句,高人为什么能够想到这些?