设计模式-工厂方法模式实例-01
工厂方法模式/虚拟构造器模式/多态工厂模式(类创建型模式)
要点:
符合开闭原则。
优点:
向客户隐藏了那种具体产品将被实例化;
能让工厂自主确定创建何种产品对象;
加入新产品时符合开闭原则。
缺点:
类的个数成对增加,在一定程度上增加了系统复杂度,带来额外开销;
增加了系统抽象性和理解难度。
适用环境:
客户端不需要知道它所需要知道的对象的类;
抽象工厂通过其子类来指定创建哪个对象。
静态工厂模式与工厂方法模式的区别:
相同点:
两个工厂方法返回类型都是超类类型。
不同点:
中心不同。简单工厂模式工厂责任过重;
工厂方法不同。简单工厂模式为静态方法,工厂方法模式为动态;
简单工厂方法不支持开闭原则,工厂方法模式支持开闭原则;
工厂方法可扩展性好。
实例1:三种支付方式的实现。
类图
代码实现:
代码结构:
AbstractPay.java:
public abstract class AbstractPay { public abstract void pay(); }
CashPay.java:
public class CashPay extends AbstractPay{ public void pay(){ System.out.println("cash pay!"); } }
CreditcardPay.java:
public class CreditcardPay extends AbstractPay{ public void pay(){ System.out.println("Creditcard pay!"); } }
PayMethodFactory.java:
import PayMethod.AbstractPay; public abstract class PayMethodFactory { public abstract AbstractPay getPayMethod(); }
CashPayFactory.java:
import PayMethod.AbstractPay; import PayMethod.CashPay; public class CashPayFactory extends PayMethodFactory{ public AbstractPay getPayMethod(){ return new CashPay(); } }
CrediticardPayFactory.java:
import PayMethod.AbstractPay; import PayMethod.CreditcardPay; public class CrediticardPayFactory extends PayMethodFactory { public AbstractPay getPayMethod(){ return new CreditcardPay(); } }
XMLUtils.java:
import org.w3c.dom.*; import javax.xml.parsers.*; import org.xml.sax.SAXException; import java.io.*; public class XMLUtils { public static Object getPayName(){ try { //创建文档对象 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document; document = documentBuilder.parse(new File("src/Utils/config.xml")); //获取包含支付方式名称的文本节点 NodeList nodeList = document.getElementsByTagName("className"); Node classNode = nodeList.item(0).getFirstChild(); String payName = classNode.getNodeValue().trim(); //通过类名生成实例对象并将其返回 Class c = Class.forName(payName); Object obj = c.newInstance(); return obj; }catch (Exception e){ e.printStackTrace(); return null; } } }
config.xml:
<?xml version="1.0"?> <config> <className>Factory.CashPayFactory</className> </config>
Client.java:
import Factory.PayMethodFactory; import PayMethod.AbstractPay; import Utils.XMLUtils; public class Client { public static void main(String[] args) { try { PayMethodFactory factory; AbstractPay payMethod; factory = (PayMethodFactory)XMLUtils.getPayName(); payMethod = factory.getPayMethod(); payMethod.pay(); }catch (Exception e){ System.out.println(e.getMessage()); } } }
测试启动项目:
此时,如果要添加一个支付方式,只需要增加一个具体类和一个具体工厂类。
例如:增加VoucherPay
VoucherPay.java:
public class VoucherPay extends AbstractPay{ public void pay(){ System.out.println("voucher pay!"); } }
VoucherPayFactory.java:
import PayMethod.AbstractPay; import PayMethod.VoucherPay; public class VoucherPayFactory extends PayMethodFactory{ public AbstractPay getPayMethod(){ return new VoucherPay(); } }
测试VoucherPay方式:
修改config.xml为:
<?xml version="1.0"?> <config> <className>Factory.VoucherPayFactory</className> </config>
测试成功!