工厂方法模式
这个什么是工厂方法模式呢?
工厂方法模式使用的频率非常高,在我们日常的开发中总能见到他的身影。其定义为:
Define an interface for creating an object,but let subclasses decide which class to instanitate Factory Method lets a class defer instantiation to subclasses
(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类)
也可以这样理解:
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Java论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
其UML图
首先来看一个有意思的小故事。就是这个女娲那个时代觉得一个人太无聊了,就想造几个和自己差不多的东西来做伴。
于是女娲就用她的八卦炉来生产我们人类。
在这个过程中涉及三个对象:女娲,八卦炉,不同的人。女娲就类似一个客户,八卦炉就是一个工厂,而人就是产品
来让我们用代码来实现这个造人计划
First
人类的总称:
package com; public interface Human { //每个人种的皮肤都有相应的颜色 public void getColor(); //人类会说话 public void talk(); }
//不同的人
package com; public class WhiteHuman implements Human { @Override public void getColor() { System.out.println("这是白种人的颜色"); } @Override public void talk() { System.out.println("这是白种人说的话"); } }
package com; //黄种人 public class YellowHuman implements Human { @Override public void getColor() { System.out.println("这是黄种人的颜色"); } @Override public void talk() { System.out.println("这是黄种人说的话"); } }
然后来创建工厂
package com; /* * 作为一个生产者来说,我们只要知道生产了什么,而不需要事物的具体信息。 * 通过分析,我们发现八卦炉生产人类的方法输入参数类型应该是Human接口的实现类 */ public abstract class AbstractHumanFactory { public abstract <T extends Human> T createHuman(Class<T> c); }
实现抽象工厂的人工类
package com; public class HumanFactory extends AbstractHumanFactory{ @Override public <T extends Human> T createHuman(Class<T> c) { //定义一个生产人种 Human human=null; try { //产生一个人 human=(Human)Class.forName(c.getName()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return (T) human; } }
测试类
package com; public class NvWa { public static void main(String[] args){ //声明阴阳八卦炉 AbstractHumanFactory YinYangLu=new HumanFactory(); System.out.println("生产白人"); Human whiteman=YinYangLu.createHuman(WhiteHuman.class); whiteman.getColor(); whiteman.talk(); } }
这是一个工厂的通用源码
//抽象产品类 public abstract class Product{ public void method1(){ } public abstract void method2(); } //具体产品类1 public class ConcreteProduct1 extends Product{ @Override public void method2() { //业务逻辑 } } //具体产品类2 public class ConcreteProduct2 extends Product{ @Override public void method2() { //业务逻辑 } } //抽象工厂类 public abstract class Cretor{ /* * 创建一个产品对象,其输入参数类型可以自行设置 * 通常String,Enum,Class 等,当然也可以为空 */ public abstract <T extends Product> T createProduct(Class<T> c); } //具体工厂类 public class ConcreteCreator extends Cretor{ @Override public <T extends Product> T createProduct(Class<T> c) { Product product=null; try { product=(Product)Class.forName(c.getName()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return (T) product; } } //场景类 public class Client{ public static void main(String[] args){ Cretor creator=new ConcreteCreator(); Product product=creator.createProduct(ConcreteProduct1.class); } }
优点:
· 首先,良好的封装性,代码结构清晰。一个对象创建时有条件约束的,如一个调用者需要一个具体的产品对象,只要知道这个产品的类名(或约束字符串)就可以了,
不用知道创建对象的艰辛过程,降低了模块间的耦合性
其次,工厂方法模式的扩展性非常优秀,只要适当的修改工厂类或扩展一个工厂类,就可以完成”拥抱变化“
再次,屏蔽产品类。这一特点非常重要,产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化
最后,工厂方法模式是典型的解耦和性框架