设计模式学习笔记二:简单工厂模式
含义:
从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。(摘自百度百科)。
另外,在Head First中说简单工厂不是一个设计模式,而像一种编程习惯。我觉得这个说的比较准确。在一个方法体中,当有大量的case when 或者 if else的时候,有“洁癖的”开发人员会进行一下简单的重构将这部分逻辑提取出来,封装成一个方法(放在当前类或一个新建的类中)。这样可以增加可读性,非常建议新人使用这种技巧,个人觉得一个方法体代码行数超过300行看着就比较累了。当封装完后发现方法体依然远远超出300行,那说明系统架构设计存在问题(一家之言)。
下面描述一个场景:
有一家电子商务公司从事酒店、机票、旅游、度假等业务。对不同业务线的订单流程我们都进行统一处理。 创建订单、订单支付、通知客人、订单最终处理。
下面看不使用简单工厂模式的实现:
/* * OrderProcessCenter.java 1.0 2014/08/11 * * 声明:欢迎转载,请注明出处。 * */ package com.liushijie.simple_factory; /** * 订单中心,负责对所有类型的订单进行操作 * @author array7 * */ public class OrderProcessCenter { public Order OrderFlow(String type) { Order order = null; if ("air".equals(type)) { // 航空组订单 order = new AirOrder(); } else if ("hotel".equals(type)) { // 酒店组订单 order = new HotelOrder(); } else if ("ticket".equals(type)) { // 门票组订单 order = new TicketOrder(); } else if ("xxx".equals(type)) { // ... // TODO: some thing } else if ("yyy".equals(type)) { // TODO: some thing } else if ("zzz".equals(type)) { // TODO: some thing } else if ("123".equals(type)) { // TODO: some thing } order.pay(); order.notifyCustomer(); order.finish(); return order; } }
通过以上代码我们可以很容易发现,假设我们要维护增改订单组必须要修改那一串逻辑判断,很明显这不符合开放原则 - 对修改关闭。我们知道要改什么,知道怎么改,那就完全可以提取出来。
同时,在业务逻辑中,创建订单本身就是一个比较专一的功能,我们完全可以将其提取出来统一进行创建操作。若要新增订单只要在专职创建订单的方法中修改即可。修改后的代码如下:
/* * OrderProcessCenter.java 1.0 2014/08/11 * * 声明:欢迎转载,请注明出处。 * */ package com.array7.simple_factory; /** * 订单中心,负责对所有类型的订单进行操作 * @author array7 * */ public class OrderProcessCenter { public Order OrderFlow(String type) { Order order = new SimpleOrderFactory().createOrder(type); order.pay(); order.notifyCustomer(); order.finish(); return order; } } package com.array7.simple_factory; public class SimpleOrderFactory { public Order createOrder(String type) { Order order = null; if ("air".equals(type)) { order = new AirOrder(); } else if ("hotel".equals(type)) { order = new HotelOrder(); } else if ("ticket".equals(type)) { order = new TicketOrder(); } else if ("xxx".equals(type)) { // TODO: some thing } else if ("yyy".equals(type)) { // TODO: some thing } else if ("zzz".equals(type)) { // TODO: some thing } else if ("123".equals(type)) { // TODO: some thing } return order; } }
提取完后又发现,这种方式还有一个优点:
创建订单成为了单独的实现,我们可以开放给我其他的调用方进行使用,实现了代码的复用。比如调用方生成订单,我们进行订单的后续跟进。