Fork me on GitHub

设计模式之简单工厂模式

简单工厂模式又叫做静态工厂方法模式,但不属于23种GOF设计模式,由于它太常用,因而将其放在首位,与后续的设计模式学习节奏保持一致。

一、模式实现

简单工厂将new对象的职责迁移到工厂中进行,通过传递的参数,在工厂中创建不同的实例化对象。下面通过具体的代码示例进行说明。

问题:某公司有一种产品,现有AB两种生产方式,现要求对其创建逻辑进行实现,并将具体的创建产品逻辑进行隔离。

现考虑用简单工厂模式的方法进行实现。

两种创建方式的功能实现代码如下:

public interface Product {
	public void operator1();
	public void operator2();
}

public class CreatProductA implements Product {

	@Override
	public void operator1() {
		System.out.println("A产品进行1操作");
	}

	@Override
	public void operator2() {
		System.out.println("A产品进行2操作");
	}
}

public class CreatProductB implements Product {

	@Override
	public void operator1() {
		System.out.println("B产品进行1操作");
	}

	@Override
	public void operator2() {
		System.out.println("B产品进行2操作");
	}
}

下面为简单工厂类的代码实现:

public class SimpleFactory {
	public static Product creatProduct(String type) {
		Product product = null;
		if ("A".equals(type)) {
			product = new CreatProductA();
		} else if ("B".equals(type)) {
			product = new CreatProductB();
		}
		return product;
	}
}

下面为客户端调用的代码:

public class Client {
	public static void main(String[] args) {
		Product productA = SimpleFactory.creatProduct("A");
		Product productB = SimpleFactory.creatProduct("B");
	}
}

SimpleFactory通过Client中传递的参数type创建不同的Product实例对象。

如下简单工厂的类图:

注意:

1、简单工厂可用来创建接口、抽象类及普通类的实例。

2、在使用简单工厂的过程中通常没有创建工厂类实例的必要,因而常将简单工厂的方法写为静态的,故又静态工厂。

3、一般应将简单工厂的创建范围控制在独立组件或模块级别,避免工厂职责混淆。

简单工厂模式调用的时序图如下:

二、模式说明

简单工厂的本质是:选择实现,简单工厂用于为客户端选择相应的实现,可通过传递参数选择适当的实现类创建实例对象。选择方式主要有以下几种:

  • 来自客户端。由客户端选择的参数选择
  • 来自配置文件,从配置文件获取参数进行选择
  • 来源于程序,通过运行期间产生的值进行选择

1、客户端传参

通过客户端参数选择如下:

public class Factory {
    public static Api creatApi(int type) {
        Api api = null;
        if (type == 1) {
            api = new ApiImpl1();
        } else if (type == 2) {
            api = new ApiImpl2();
        }
        return api;
    }
}

其中creatApi方法中根据传入的type值,创建不同的Api对象。

缺点:客户端需理解传入的type值的含义,一定程度上暴露了代码的内部实现细节

2、配置文件传参

若添加新的创建API方法,则每次要修改工厂类,因而考虑其他实现工厂的方式,可通过配置文件的方式进行。

一般开发中采用properties文件或xml文件方式进行配置:

ApiImpl=com.luis.service.impl.ApiImpl3

此时工厂的代码如下:

public class Factory {
	public static Api creatApi() {
		Properties p = new Properties();
		InputStream is = null;
		try {
			is = Factory.class.getResourceAsStream("ApiFactory.properties");
			p.load(is);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		Api api = null;
		try {
			api = (Api) Class.forName(p.getProperty("ApiImpl")).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return api;
	}
}

可通过配置文件实现简单工厂创建不同的实例化对象。

三、模式总结

1、使用场景

  • 需要完全封装隔离具体实现,外部只通过接口访问封装体,无需关心具体实现

  • 将创建对象的职责集中管理控制

2、模式优缺点

优点:

  • 帮助封装,真正实现面向接口编程。
  • 解耦,通过简单工厂实现客户端与具体实现类的解耦。
  • 简单工厂可通过一个含参的工厂方法,实例化任何产品类,戏称“上帝类”。

缺点:

  • 增加客户端复杂度。通过客户端传参数在工厂中进行创建,增加客户端使用难度,暴露了内部实现。
  • 子工厂难扩展。私有化简单工厂的构造方法,使用静态方法创建接口,不方便子工厂的扩展。
  • 当所要生产产品种类非常多时,工厂方法的代码量可能会很庞大。
  • 遵循开闭原则(对拓展开放,对修改关闭)的条件下,简单工厂对于增加新的产品,只能通过修改工厂方法来实现。

参考:文章主要参考《研磨设计模式》一书

posted @ 2019-01-30 21:46  紫焱luis  阅读(313)  评论(0编辑  收藏  举报