工厂模式相当于创建对象的new。如 A a = new A(). 工厂模式也是用来创建实例对象的,但它是面向接口编程,提高了代码的扩展性和维护性。像Hibernate 换数据库只需换方言和驱动就可以,这也是工厂模式的实现
例:这两天加班太累了,想去按摩店按摩。每位技师都有不同的特长,我只需要告诉经理我要什么服务,她就能安排,我不需要管具体是哪位技师。
//创建对象的接口 public interface Massage { //需要按摩服务 public void massagist(); } class Massage1 implements Massage{ @Override public void massagist() { System.out.println("7号技师为您泰式足底按摩90分钟"); } } class Massage2 implements Massage{ @Override public void massagist() { System.out.println("13号技师为您精油推背90分钟"); } } class Massage3 implements Massage{ @Override public void massagist() { System.out.println("27号技师为你前列腺按摩120分钟"); } }
工厂类
public class MassageFactory { // 获取对象实例 public static Massage getInstance(String massageName) { Massage massage = null; if(massageName.equals("Massage1")) { massage = new Massage1(); } if(massageName.equals("Massage2")) { massage = new Massage2(); } if(massageName.equals("Massage3")) { massage = new Massage3(); } return massage; } public static void main(String[] args) { Massage massage = MassageFactory.getInstance("Massage2"); massage.massagist(); } } ============== 【控制台输出】 13号技师为您精油推背90分钟
可以发现普通工厂模式中,每当我们新增加一个子类的时候,就需要去修改工厂类里面的方法,这样的程序是不具有扩展性的。
Java反射优化工厂类
public class MassageReflexFactory { // 获取对象实例 public static Massage getInstance(String massageName) { Massage massage = null; try { // 通过className反射动态获取class文件 Class<?> classInfo = Class.forName(massageName); // 获取对象实例 massage = (Massage)classInfo.newInstance(); } catch (Exception e) { // TODO: handle exception } return massage; } public static void main(String[] args) { Massage massage = MassageFactory.getInstance("Massage1"); massage.massagist(); } } ================= 【控制台输出】 7号技师为您泰式足底按摩90分钟
对比可以发现,无论接口有多少个子类实现我们都不需要修改工厂类的方法,只需要传入类名称就能获取对象。反射机制通过动态创建对象进行反编译获取类的属性,使得代码更加灵活,更容易实现面向对象。
spring中工厂模式的实现
// 创建bean工厂 public interface BeanFactory { Object getBean(String id) throws ExecutionException; } // Bean工厂的实现类 public class ClassPathXmlApplicationContext implements BeanFactory { private Map<String, Object> map = new HashMap<String, Object>(); @SuppressWarnings("unchecked") public ClassPathXmlApplicationContext(String fileName) throws DocumentException, InstantiationException, IllegalAccessException, ClassNotFoundException { //加载配置文件 SAXReader reader = new SAXReader(); Document document = reader.read(ClassPathXmlApplicationContext.class.getClassLoader().getResourceAsStream(fileName)); //获取根节点 Element root = document.getRootElement(); //获取子节点 List<Element> childElements = root.elements(); for (Element element : childElements) { map.put(element.attributeValue("id"), Class.forName(element.attributeValue("class")).newInstance()); } } @Override public Object getBean(String id) throws ExecutionException { return map.get(id); } }