工厂方法模式
工厂方法模式是简单工厂模式的延伸,它继承了简单工厂模式的优点,同时弥补了简单工厂的缺陷,更好地符合开闭原则的要求,增加新的具体产品对象不需要对已有系统作任何修改。
模式定义
工厂方法模式又称为工厂模式,也叫虚拟构造器模式或者多态工厂模式,属于类创建模式。在工厂模式中,工厂父类负责定义产品对象的公共接口,而子工厂模式负责生成具体的产品对象,这样做的目的是将产品类实例化操作延迟到工厂子类中完成,即通过工厂子类来确定实例化哪一个对象。
模式结构
Product(抽象产品)
抽象产品是定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的共同父类接口
ConcreteProduct(具体产品)
具体产品实现抽象产品接口,某种类型的具体产品由专门具体创建
Facory(抽象工厂)
在抽象工厂类中,声明工厂方法,用于返回一个产品。抽象工厂是工厂方法模式的核心,任何在模式中创建对象的工厂类都必须实现该接口。
ConcreteFactory(具体工厂)
具体工厂是抽象工厂类的子类,实现了抽象工厂定义的工厂方法,返回一个具体产品类的实例。
模式分析
在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建的工作交给了子类。核心类仅仅给出具体工厂实现的接口,而不负责哪一个产品被实例化的细节,使得工厂方法模式允许系统在不修改工厂角色的情况下引进新产品。
实际的开发应用中,不直接使用new关键字来创建对象,而是将具体类的类名写入配置文件,在通过java反射机制,读取XML格式的配置文件,根据存储在XML文件的类名字符串生成对象。
工厂方法模式实例之手机工厂
实例说明
之前的简单工厂模式时我们也创建过一个类似实例,但却是违反了开闭原则的。通过工厂方法模式进行一次重构,将原有工厂进行分割,为每种品牌的手机提供一个子工厂,使整个系统具有更好的灵活性和可扩展性。
实例类图
实例代码及解释
抽象产品类Phone
public abstract class Phone { public abstract void use(); }
具体产品类HuaweiPhone
public class HuaweiPhone extends Phone { @Override public void use() { System.out.println("华为手机使用中...."); } }
具体产品类XiaomiPhone
public class XiaomiPhone extends Phone { @Override public void use() { System.out.println("小米手机使用中...."); } }
抽象工厂类PhoneFactory
public interface PhoneFactory { Phone producePhone(); }
具体工厂类HuaweiPFactory
public class HuaweiPFactory implements PhoneFactory { @Override public Phone producePhone() { System.out.println("华为工厂生产华为手机......"); return new HuaweiPhone(); } }
具体工厂类XiaomiPFactory
public class XiaomiPFactory implements PhoneFactory { @Override public Phone producePhone() { System.out.println("小米工厂生产小米手机......"); return new XiaomiPhone(); } }
XML操作工具类
public class XMLUtilPhone { public static Object getBean() throws Exception { //创建解析器工厂 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); //创建解析器 DocumentBuilder builder = builderFactory.newDocumentBuilder(); //得到document Document document = builder.parse("configPhone.xml"); //获取包含品牌名称的文本节点 NodeList brandNameList = document.getElementsByTagName("factoryName"); Node classNode = brandNameList.item(0).getFirstChild(); String factoryName = classNode.getNodeValue().trim(); // System.out.println(factoryName); Class c = Class.forName("com.factoryMethod." + factoryName); Object o = c.newInstance(); return o; } }
配置文件
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <factoryName>XiaomiPFactory</factoryName> </configuration>
测试类
public class Test { public static void main(String[] args) throws Exception { PhoneFactory phoneFactory = (PhoneFactory) XMLUtilPhone.getBean(); Phone phone = phoneFactory.producePhone(); phone.use(); } }
结果分析
如果在配置文件将节点中内容设置为 XiaomiPFactory,则输出结果如下:
如果在配置文件将节点中内容设置为 XiaomiPFactory,则输出结果如下:
如果需要增加新的类型的手机,则首先要增加一个新的具体产品类,再增加对于的具体工厂类。