上次对“简单工厂模式”的使用进行了总结,讲解过程中使用了在“网上商城”买东西的例子。大家也许注意到了所有商品的实例化都是在一个工厂类ProductFactory中完成,如果商城有数十万个商品,都在一个工厂类中实现肯定是不现实的。这时最容易想到的方式,是对商品进行分类,不同的类型采用不同的“工厂”创建,这就是产生了“工厂方法模式”。“商城”只需要定义好接口,具体的工厂实现交给具体的商家实现即可。
工厂方法模式
工厂方法模式定义了一个创建对象的接口(抽象类),但由子类决定要实例化的类是哪一个(目标对象),工厂方法让类把实例化推迟到了子类。这里其实有三种角色:抽象的创建接口、具体的创建工厂类、目标对象(对应还有一个目标基类),具体的创建工厂类继承自抽象接口类,其作用是根据不同的条件创建不对的目标对象。这就是所谓的把创建对象的决定权交给子类,从而实现完全基于接口编程,而不必在意具体的实现(相对于简单工厂模式)。下面来看下工厂方法模式的类图:
这里的ProductFactoryA、ProductFactoryB分布都可以创建两类对象,也可以只创建一类对象。AbsClient里公共的业务方法,以及抽象的工程方法由于创建具体的目标对象,ProductFactoryA和ProductFactoryB实现这个方法。
该模式的核心是把公共的业务方法提取到AbsClient基类中(参考上一章中的Client类的orderProduct方法),在依赖具体目标对象的地方使用Iproduct接口代替,具体创建这些对象的工作交给AbsClient的子类去实现;同时为了方便扩展,AbsClient的子类根据业务需要可以有多个,这些子类都是具体的工厂类,每个工厂类可以创建同一类Product。比如这里ProductFactoryA可以创建Product1、Product2,ProductFactoryB可以创建Product3、Product4。可以把每个工厂类看做是一个商家的工厂,“网上商城”AbsClient 要增加自己的商品品类,可以接入不同的商家入驻即可(实现新的工厂类,创建新的商品类),原有已存在的代码无需任何改动。
这里不再使用商城的列子,感兴趣的朋友可以自己实现。下面以实际项目中一个例子进行讲解。
模式示例
这里以笔者真实项目中的场景为例:该项目是一个页面的在线编辑系统,页面编辑好后会有发布动作,该动作会触发数据保存(saveData方法)、发起页面渲染请求(sendRender方法)、向MQ发送消息(sendMq方法)。如果只有一类页面该流程实现起来很简单,但现在有4个不同业务类型对应的页面:pc活动页、pc店铺页、m活动页、m店铺页,后续还有可能增加别的业务类型对应的页面。这里其实就可以采用工程方法模式,来创建不同的业务对象进行处理。首先来看下类图,对应上面的类图,只是类名上有改动:
首先来看抽象基类AbsPublish
public abstract class AbsPublish { private BusinessService businessService; /** * 页面发布方法 */ public void publish(String type,Integer id){ businessService = createBusiness(type); //step1 保存页面配置数据 businessService.saveData(id); //step2 发起渲染请求 businessService.sendRender(id); //step3 把该活动信息发布到“已发布消息队列” businessService.sendMq(id); //其他公共操作 printLog(type,id); } private void printLog(String type,Integer id){ System.out.println("类型:"+type+"编号:"+id+"发布完成"); } protected abstract BusinessService createBusiness(String type); }
publish方法是就是页面发布的通用流程,分别会触发数据保存(saveData方法)、发起页面渲染请求(sendRender方法)、向MQ发送消息(sendMq方法)。这三个方法在不同的业务类型对应的实现不同,但这里不用管具体的实现。具体的实现交给createBusiness(String type)方法去创建,该方法收抽象方法,交给子类实现。
ActPublish、ShopPublish是AbsPublish两个子类,主要方作用就是实现createBusiness方法,创建具体的业务对象。
public class ActPublish extends AbsPublish { @Override protected BusinessService createBusiness(String type) { BusinessService businessService = null; if("mAct".equals(type)){ businessService = new MActBusinessImpl(); }else if ("pcAct".equals(type)){ businessService = new PcActBusinessImpl(); } return businessService; } }
public class ShopPublish extends AbsPublish { @Override protected BusinessService createBusiness(String type) { BusinessService businessService = null; if("mShop".equals(type)){ businessService = new MShopBusinessImpl(); }else if ("pcShop".equals(type)){ businessService = new MShopBusinessImpl(); } return businessService; } }
接下来再来看下业务基类和业务实现类:
public interface BusinessService { /** * 保存数据库 */ void saveData(Integer id); /** * 发起页面渲染请求 */ void sendRender(Integer id); /** * 向mq(消息队列)发送页面发布消息 */ void sendMq(Integer id); }
MActBusinessImpl、MShopBusinessImpl、PcActBusinessImpl、PcShopBusinessImpl是具体的业务实现类,这里只列出MActBusinessImpl实现代码,实现具体业务逻辑已省略,可以自行实现:
public class PcShopBusinessImpl implements BusinessService { public void saveData(Integer id) { System.out.println("pc店铺:配置数据入库"); } public void sendRender(Integer id) { System.out.println("pc店铺:发起页面渲染请求"); } public void sendMq(Integer id) { System.out.println("pc店铺:把该活动信息推送到 已发布pc店铺mq(消息队列)"); } }
最后创建main方法测试,模拟发布编号为12345的m活动页:
public class Main { public static void main(String[] args) { AbsPublish mAct = new ActPublish(); mAct.publish("mAct",12345); } }
运行main方法:
M活动:配置数据入库 M活动:发起页面渲染请求 M活动:把该活动信息推送到 已发布M活动mq(消息队列) 类型:mAct编号:12345发布完成
如果要新增一个业务逻辑,新增一个工厂类和具体的业务实现类即可。
小结
使用工厂方法模式,可以把具体的实现延迟到子类中进行,满足了 oo设计原则中的针对接口编程和不针对实现,以及开闭原则(对修改关闭,都扩展开放)。缺点,就是会创建很多的工厂类实现和具体业务类实现,但可以把这部分实现交给第三方,主体业务只负责定义规则(创建接口),实现业务解耦。
出处:
相关推荐
工厂方法模式将具体的对象创建过程延迟到子类中,通过接口或抽象类定义创建对象的方法,每个子类对应一个具体的产品。这种方式使得系统更具有扩展性,增加了新的产品只需添加新的子类即可,无需修改原有代码。工厂...
工厂方法模式是面向对象设计模式中的一个创建型模式,它提供了一种封装对象创建过程的方式,使得具体的对象创建过程可以延迟到子类中进行。在C++编程中,工厂方法模式广泛应用于各种软件设计中,因为它能有效地解耦...
- 定义:工厂方法模式将对象的创建延迟到子类,父类定义了创建对象的接口,但由各个子类决定实例化哪个类。这样,每个子类都可以决定其创建的产品类型。 - UML图表示:工厂方法模式的UML图包括一个抽象工厂类,一...
工厂方法模式将对象的创建过程进一步抽象,将具体的对象创建延迟到子类中。工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。这样,工厂方法让类的实例化推迟到子类。在C#中,可以通过...
它将对象的创建延迟到子类中进行,使得代码更加模块化,易于维护和扩展。工厂方法模式通常只有一个方法,这个方法负责创建一个特定的产品。在实际应用中,如果需要创建的对象具有共同的接口或基类,但具体类型是由...
2. **工厂方法模式**:将具体产品的实例化延迟到子类中进行,工厂接口定义了创建对象的协议,但不直接实例化对象,而是由每个子类自己决定实例化哪个具体产品。这种方式增强了系统的灵活性,易于扩展新的产品。 3. ...
**工厂方法模式**:这是一种更为灵活的工厂模式变体,它将对象的创建延迟到子类中进行。在工厂方法模式中,父类定义了一个创建对象的接口,但由子类来决定要实例化的具体类。这种方式使得系统更具可扩展性,当需要...
工厂方法模式的核心优势是,它将对象的创建延迟到子类中,因此在添加新产品时,只需添加新的子类即可,无需修改现有的代码。 工厂方法模式让系统更加灵活和可扩展,因为它支持在运行时创建多个具体类的实例。这意味...
本资源主要介绍工厂方法模式和抽象工厂模式。二者都与工厂相关,,但是其... 工厂方法模式:它将对象的创建延迟到子类中进行。由子类决定具体实例化哪个类。通过切换具体工厂的子类,来改变单个实例(也可说产品)。
工厂方法将一个类的实例化延迟到其子类。这种方式提供了一种封装对象创建的方式,使得客户端代码不必知道具体创建的是哪个类的对象,提高了代码的灵活性和可扩展性。 2. **简单工厂(Simple Factory)**: 简单...
同时,工厂方法模式也可以避免简单工厂模式的缺点,即当有新产品要加入到系统中时,必须对工厂类进行修改,以加入必要的处理逻辑。 工厂方法模式适合在如下场合中运用: * 当无法得知必须创建的对象属于哪个类的...
工厂方法模式提供了一种封装对象创建过程的方法,使得具体的创建过程延迟到子类中进行,从而实现了类的抽象化与具体实现的分离,提高了代码的可扩展性和可维护性。 ### 标题解析: “设计模式之工厂方法模式”表明...
在C#中,我们可以利用这种模式来抽象产品的创建过程,将具体的实例化操作延迟到子类中进行,从而实现代码的解耦和扩展性。 1. **模式定义** 工厂方法模式定义了一个创建对象的接口,但让实现这个接口的类来决定...
工厂方法模式是一种将对象的创建过程延迟到子类中实现的策略。它定义了一个创建对象的接口,但让子类决定实例化哪一个类。在工厂方法模式中,工厂角色(Factory)不再直接创建产品,而是由具体工厂(Concrete ...
与简单工厂模式不同,工厂方法模式将对象的创建延迟到了子类,使得系统更易于扩展。 #### 1. 角色分析 - **抽象工厂类**:定义一个创建对象的接口,让子类决定实例化哪一个类。抽象工厂本身不直接实例化对象,而是...
在工厂方法模式中,我们定义了一个用于创建对象的接口,但让子类决定实例化哪一个类。该模式将实例化推迟到子类。 工厂方法模式包含四个主要角色: 1. **抽象产品(Product)**:定义了产品的接口。 2. **具体产品...
总结,本项目通过工厂方法模式重构简易计算器,展示了这种模式在处理多类型对象创建问题时的灵活性和可扩展性。这种方法使得代码结构清晰,易于维护,同时也为添加新功能提供了便利。对于学习设计模式和实践面向对象...
这样,工厂方法将实例化对象的过程延迟到了子类,实现了对具体类的解耦。在Java或其他面向对象语言中,通常表现为一个抽象类或接口定义了一个工厂方法,而各个具体的子类重写这个方法来创建对应的实例。这种模式的一...
工厂方法模式是一种面向对象的设计模式,属于创建型模式,它提供了一种创建对象的最佳方式。在工厂方法模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为模式。 工厂方法模式的核心思想是...
工厂方法模式定义了一个创建对象的接口,但让子类决定实例化哪一个类。工厂方法让类的实例化推迟到子类中进行,实现了对责任的分割,降低了系统的耦合度。 2. **角色与结构**: - **产品接口(Product)**:定义了...