Java设计模式之工厂模式
首先,学习模式,一定不能生搬硬套,一定要明天它的好处,为什么要用这个模式,以及这个模式的特点是什么。
对于工厂模式,我们最熟悉的就是spring里面的bean对象了。它起到解耦的作用。如果我们每次用到对象都new一个,那么当我们需要修改的时候
就会很麻烦,得一个一个的修改,这样不利于程序的解耦。这是它的主要作用,那么它的特点呢?
在代码里我们应该怎么写呢?工厂模式有很多种。
有简单工厂模式:用一个类去创建其他类的实例,父类是相同的,子类是具体的,那么这局限创造的范围
工厂方法模式:它的特点是一个抽象工厂可以派生出多个具体的工厂,而每个具体的工厂又可以对一个具体的对象进行创建
抽象工厂模式:它的特点是一个抽象工厂可以派生出多个具体的工厂,而每个具体的工厂可以对某一类对象进行创建
从上面三个模式可以看出,其实工厂模式的核心就是对类进行管理,那么我们抓住这个核心,就可以任意创建我们需要的模式
spring里面的工厂模式就是一个很好的例子-----程序启动时自动扫描需要创建的对象,把他们保存到一个map里面,当我们其他的类依赖它们的时,
就通过注解的value值反射出它们的实例并注入。
首先,学习模式,一定不能生搬硬套,一定要明天它的好处,为什么要用这个模式,以及这个模式的特点是什么。
对于工厂模式,我们最熟悉的就是spring里面的bean对象了。它起到解耦的作用。如果我们每次用到对象都new一个,那么当我们需要修改的时候
就会很麻烦,得一个一个的修改,这样不利于程序的解耦。这是它的主要作用,那么它的特点呢?
在代码里我们应该怎么写呢?工厂模式有很多种。
有简单工厂模式:用一个类去创建其他类的实例,父类是相同的,子类是具体的,那么这局限创造的范围
工厂方法模式:它的特点是一个抽象工厂可以派生出多个具体的工厂,而每个具体的工厂又可以对一个具体的对象进行创建
抽象工厂模式:它的特点是一个抽象工厂可以派生出多个具体的工厂,而每个具体的工厂可以对某一类对象进行创建
从上面三个模式可以看出,其实工厂模式的核心就是对类进行管理,那么我们抓住这个核心,就可以任意创建我们需要的模式
spring里面的工厂模式就是一个很好的例子-----程序启动时自动扫描需要创建的对象,把他们保存到一个map里面,当我们其他的类依赖它们的时,
就通过注解的value值反射出它们的实例并注入。
学习语言,无外乎多写多看多思多想,下面我自己写一下一个简单的实现,用来做自己的知识的积累:
首先:看看这个工厂类:
package testfactory;
import java.util.Map;
import testfactory.bean.Student;
public class BeanFactory {
public static Object getBean(String beanName) throws Exception{
Map<String,String> clazzs= ClassScanUtil.getClassFormPackage("testfactory.bean");
String clazz= clazzs.get(beanName);
Object object=Class.forName(clazz).newInstance();
return object;
}
public static void main(String[] args) throws Exception {
Student student=(Student) getBean("student");
student.study();
}
}
只需要得到类的名字就能得到这个类的具体的实例,其实这有些像spring的工厂模式,只不过spring的工厂模式面对的是接口,是得到这个接口下面的某个实现类,这
里只是一个简化版,下面看看ClassScanUtil如何实现:
package testfactory;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ClassScanUtil {
public static Map<String,String> getClassFormPackage(String packagePath) throws IOException, ClassNotFoundException{
Map<String,String> clazzs = new HashMap<String,String>();
String path=packagePath.replace(".", "/");
File directory =new File("");//设定为当前文件夹
//定义一个枚举的集合 并进行循环来处理这个目录下的文件
Enumeration<URL> dirs;
//得到资源路径
dirs=Thread.currentThread().getContextClassLoader().getResources(path);
if(dirs.hasMoreElements()){
URL url=dirs.nextElement();
//System.out.println(url.getFile());
File file=new File(url.getFile());
String[] strs=file.list();
for(String str:strs){
//得到这个路径下的所有class文件。这里只是 一个简版,默认是路径下只有class文件不存在文件包,
//如果想做的复杂可以看看file.list()一个需要过滤器的重载方法
Class clazz=Class.forName(packagePath+"."+str.split("\\.")[0]);
//这里是个自定义的注解,只有注解的类才能用于工厂生产
FactoryMap factoryMap=(FactoryMap) clazz.getAnnotation(FactoryMap.class);
if(factoryMap!=null){
String s=isEmpty(factoryMap.value())?str.split("\\.")[0].toLowerCase():factoryMap.value();
clazzs.put(isEmpty(factoryMap.value())?str.split("\\.")[0].toLowerCase():factoryMap.value(), packagePath+"."+str.split("\\.")[0]);
}
}
}
return clazzs;
}
public static boolean isEmpty(String str){
if(str==null||str.equals("")||"null".equals(str)){
return true;
}else{
return false;
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
getClassFormPackage("testfactory.bean");
}
}
下面看看注解的实现:
package testfactory; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE)//用于描述类、接口(包括注解类型) 或enum声明 @Retention(RetentionPolicy.RUNTIME)//运行时保留 @Documented public @interface FactoryMap { String value() default ""; }
只要在指定的包下的类加入这个注解,就能用BeanFactory的geBean方法得到这个类的具体事例:
这是今天对工厂的学习,每天进步一点点package testfactory.bean; import testfactory.FactoryMap; @FactoryMap() public class Student { public void study(){ System.out.println("学生爱学习"); } }