设计模式:工厂方法模式

📅 2026/6/16 1:21:03
设计模式:工厂方法模式
工厂方法模式别再到处 new 对象让子类决定该创建谁目录new 有什么问题工厂方法模式是什么代码实现物流系统的运输方式工厂方法模式和简单工厂模式的区别实际应用小结new 有什么问题假设你接手了一个电商系统的订单模块代码里到处写着这种东西// 订单服务里AlipayPaymentpaymentnewAlipayPayment();payment.pay(order.getAmount());// 退款服务里AlipayPaymentpaymentnewAlipayPayment();payment.refund(order.getAmount());// 对账服务里AlipayPaymentpaymentnewAlipayPayment();payment.reconcile(order.getRecords());三个服务都直接new AlipayPayment()。现在需求来了接入微信支付。你得满项目找new AlipayPayment()逐个判断该换成new WechatPayment()还是保留。这可得找到什么时候啊。问题的根源在于调用方既关心用什么又关心怎么造。这两件事耦合在一起改任何一个都得动另一个。那如果把怎么造这件事抽出去调用方只管使用呢工厂方法模式是什么工厂方法模式定义一个创建对象的抽象方法让子类决定具体创建谁。类比一下点外卖的场景。你在美团上点了一份黄焖鸡你只关心下单、等餐、收货这个流程。至于这道菜是哪个厨师做的、用的哪个灶台、从哪个锅里盛出来的你完全不关心。平台负责把做一份黄焖鸡这个需求派给合适的商家商家决定怎么做。调用方通过工厂方法拿到对象不直接new。具体创建谁交由子类说了算。代码实现物流系统的运输方式用一个物流系统的例子来走一遍完整实现。系统需要支持卡车、轮船、飞机三种运输方式未来还会加更多。产品接口先定义所有运输方式的共同接口publicinterfaceTransport{Stringdeliver();}调用方只认这个接口。至于底层是卡车还是飞机它不知道也并不关注。具体产品三种运输方式各自实现接口publicclassTruckimplementsTransport{OverridepublicStringdeliver(){return卡车陆运货物;}}publicclassShipimplementsTransport{OverridepublicStringdeliver(){return轮船海运货物;}}publicclassAirplaneimplementsTransport{OverridepublicStringdeliver(){return飞机空运货物;}}抽象创建者这是工厂方法模式最关键的部分。创建者是一个抽象类它定义了工厂方法但不实现它publicabstractclassLogistics{// 定义抽象方法工厂方法返回类型是接口不是具体类protectedabstractTransportcreateTransport();// 业务逻辑只依赖接口publicvoidshipGoods(){TransporttransportcreateTransport();System.out.println(transport.deliver());}}createTransport()是抽象的父类只说给我一个运输工具至于是什么由子类定。shipGoods()是业务方法它拿到的是Transport接口永远不碰具体类。具体创建者子类重写工厂方法各自决定创建什么publicclassRoadLogisticsextendsLogistics{OverrideprotectedTransportcreateTransport(){returnnewTruck();}}publicclassSeaLogisticsextendsLogistics{OverrideprotectedTransportcreateTransport(){returnnewShip();}}publicclassAirLogisticsextendsLogistics{OverrideprotectedTransportcreateTransport(){returnnewAirplane();}}每个子类只管一件事创建哪个产品。它不关心产品创建之后怎么使用。使用LogisticslogisticsnewRoadLogistics();logistics.shipGoods();// 卡车陆运货物logisticsnewSeaLogistics();logistics.shipGoods();// 轮船海运货物调用方决定用哪个子类子类决定创建哪个产品。创建决策从一行new变成了一个可扩展的继承体系。现在要加火箭运输加两个类就行Rocket implements TransportRocketLogistics extends Logistics。已有代码一行不改。整个流程串起来长这样工厂方法模式和简单工厂模式的区别你可能会说搞这么复杂干嘛直接写一个工厂类不可以吗publicclassTransportFactory{publicstaticTransportcreate(Stringtype){switch(type){casetruck:returnnewTruck();caseship:returnnewShip();caseairplane:returnnewAirplane();default:thrownewRuntimeException(不支持type);}}}简单工厂模式确实可用。但两者有本质区别简单工厂是把所有创建逻辑塞进一个 switch工厂方法是把每个创建逻辑拆到各自的子类里。什么时候适合用简单工厂产品就两三种并且创建逻辑简单、基本不会扩展的时候简单工厂更直接就没必要搞继承。什么时候用工厂方法产品类型会持续增长、创建逻辑各有差异、需要符合开闭原则的时候工厂方法则更加合适。小结工厂方法模式解决的问题很直接别让调用方自己new对象。把创建逻辑抽到一个抽象方法里让子类决定创建什么调用方只管使用。这样新增产品只需要增加实现类和对应的创建子类老代码无需改动。