工厂设计模式
工厂方法模式使用的频率非常高,其定义如下:
- Define an interface creating object , but let subclasses decide which class to instantiate . Factory Method lets a class defer instantiation to subclasses .
- 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
工厂方法的通用UML类图如下所示:

上图中各类的职责:
- 抽象产品类(Product):负责定义产品的共性,实现对事物最抽象的定义。
- 实现产品类(ConcreteProduct):具体产品。
- 抽象创建类(Creator):也就是抽象工厂。
- 实现工厂类(ConcreteCreator):创建产品类。
下面是一个比较实用的通用源码:
//抽象产品类
public abstract class Product{
//产品的共性方法
public void method_1(){
//具体逻辑
}
//抽象方法
public abstract void method_2();
}
//具体产品类可以有多个,都继承于抽象产品类
public class ConcreteProduct_1 extends Product{
public void method_2(){
//具体逻辑
}
}
public class ConcreteProduct_2 extends Product{
public void method_2(){
//具体逻辑
}
}
......
//抽象工厂类
public abstract class Creator{
/**
*创建一个产品对象,其输入参数类型可以自行设置
*通常是String、Enume、Class等,也可以为空
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}
//具体工厂类
public class ConcreteCreator extends Creator{
public abstract <T extends Product> T createProduct(Class<T> c){
Product product = null;
try{
product = (Product)Class.forName(c.getName().newInstance);
}catch(Exception e){
//异常处理
}
return (T)product;
}
}
//场景类
public class Client{
public static void main(String[] args){
Creator creator = new ConcreteCreator();
Product product = creator.createProduct(ConcreteProduct1.class);
//继续业务处理
}
}
1.工厂方法模式的优点
- 良好的封装性,代码结构清晰
- 工厂方法模式的扩展性非常优秀
- 屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不要发生变化。
- 工厂方法模式是典型的解耦框架。符合迪米特法则、依赖倒置原则和里氏替换原则。
2.工厂模式的使用场景
- 工厂方法模式是new一个对象的替代品,在所有需要生成对象的地方都可以使用。
- 需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。
- 工厂方法模式可以用在异构项目中。
- 可以使用在测试驱动开发的框架下。
3.工厂方法模式的扩展
- 缩小为简单工厂模式
- 升级为多个工厂类
- 替代单例模式
- 延迟初始化
替代单例模式的代码示例:
//单例类
public class Singleton{
//不允许通过new产生一个对象
private Singleton(){
}
public void doSomrthing(){
//业务处理
}
}
//负责生产单例的工厂类
public class SingletonFactory{
private static Singleton singleton;
static{
try{
Calss cl = Class.forName(Singleton.class.getName());
//获得无参构造
Constructor constructor = c1.getDeclaredConstructor();
//设置无参构造是可访问的
constructor.setAccessible(true);
//产生一个实例对象
singleton = (Singleton)constructor.newInstance();
}catch(Exception e){
//异常处理
}
}
public static Singleton getSingleton(){
return singleton;
}
}
简单工厂模式(Simple Factory Pattern)
这种模式属于类的创新型模式,也称静态工厂方法模式,通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
1.UML图示
简单工厂模式的UML图如下所示:

简单工厂模式中包含的角色及其相应的职责如下:
- 工厂角色(SimpleFactory):是简单工厂模式的核心,由它负责创建所有的类的内部逻辑。当然工厂类必须能够被外界调用,创建所需要的产品对象。
- 抽象(Product)产品角色:简单工厂模式所创建的所有对象的父类,注意,这里的父类可以是接口也可以是抽象类,它负责描述所有实例所共有的公共接口。
- 具体产品(Concrete Product)角色:简单工厂所创建的具体实例对象,这些具体的产品往往都拥有共同的父类。
简单工厂模式的核心思想就是有一个专门的类来负责创建实例的过程。
2.简单工厂模式的优缺点
优点:
- 工厂类是整个模式的关键所在。它包含了必要的判断逻辑,能够根据外界给定的信息决定究竟应该创建哪个具体的对象。
- 用户在使用时可以直接根据工厂类去创建所需的实例,而无需了解这些对象是如何创建以及如何组织的,有利于整个软件体系结构的优化。
缺点:
- 由于工厂类集中了所有实例的创建逻辑,所以一旦工厂出了问题,所有的客户端都会受到牵连。
- 有不同的产品接口或抽象类时,工厂类需要判断何时创建何种种类的产品。违背了单一职责原则,导致系统丧失灵活性和可维护性。
- 简单工厂模式违背了开放封闭原则,因为当新增一个产品时,必须修改工厂类,响应的工厂类就需要重新编译一遍。
- 简单工厂模式的方法都是静态的,是无法让子类继承的,所以简单工厂模式无法形成基于基类的继承树结构。
温馨提示:
严格意义上讲,简单工厂模式并不算是一种设计模式,简单工程模式更像是一种编程习惯。简单工厂模式不利于构建容易发生变化的系统。
示例代码如下:
public class IFood{
void eat();
}
public class Chips implements IFood{
public void eat(){
System.out.println("我们吃到了薯条......");
}
}
public class McChicken implements IFood{
public void eat(){
System.out.println("我们吃到了麦香鸡......");
}
}
public class Mcdolad{
public IFood getFood(String name){
switch(name){
case "chip":
return new Chips();
break;
case "mcChicken":
return new McChicken();
break;
default:
System.out.println("我们不生产该产品....");
break;
}
}
}
public class Client{
public static void main(String[] args){
Mcdolad mcdolad = new Mcdolad();
IFood food = mcdolad.getFood("chip");
if (food!=null){
food.eat();
}
IFood food = mcdolad.getFood("mcChicken");
if (food!=null){
food.eat();
}
IFood food = mcdolad.getFood("kfcChicken");
if (food!=null){
food.eat();
}
}
}
抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的。抽象工厂模式可以向客户端提供一个接口,是客户端在不必指定产品的具体类型的情况下,能够创建多个产品族的产品对象。
(Provide an interface for creating families of related or dependent objects without specifying their concrete classes 。)
1.抽象工厂模式的UML图示

抽象工厂模式中的角色和其职责:
- 抽象工厂(AbstractFactory):抽象工厂模式的核心,包含对多个产品结构的声明,任何工厂类都必须实现这个接口。
- 具体工厂(ConcreteCreator):具体工厂类是抽象工厂的一个实现,负责实例化某个产品族中的产品对象。
- 抽象产品(AbstractProduct):抽象模式所创建的所有对象的父类,负责描述所有实例所共有的公共接口。
- 具体产品(Concrete Product):抽象模式所创建的具体实例对象。
2.抽象工厂模式的优缺点
优点:
- 封装性。每个产品的实现类不是高层模块要关心的,它要关心的是接口或抽象,不关心对象是如何创建的。
- 产品族内的约束为非公开状态。在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,符合了开闭原则。
缺点:
- 产品族扩展非常困难。产品族就是指不同产品等级结构中,功能相关联的产品组成的家族。每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使系统中类的个数成倍增加。在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
注意:
- 一个对象族都有相同的约束,则可以使用抽象工厂模式。
- 抽象工厂模式的产品族扩展困难,而不是产品等级扩展困难。增加一个产品等级,只要增加一个工厂类负责新增加出来的产品生产任务即可。
与简单工厂的对比:
- 工厂方法模式是简单工厂模式的延伸、在工厂方法模式中,核心工厂类不再负责产品的创建,而是将具体的创建工作交给子类去完成。也就是核心工厂仅仅只是提供创建的接口,具体实现方法交给继承它的子类去完成。当系统需要增加其他新的对象时,只需要添加一个具体的产品和它的创建工厂即可,不需要对原工厂进行任何修改,很好地符合了开闭原则。
示例代码如下:
public interface IChips{
public void eat();
}
public class MCchips implements IChips{
public void eat(){
System.out.println("吃到了MCchips....");
}
}
public class KFCchips implements IChips{
public void eat(){
System.out.println("吃到了KFCchips....");
}
}
public class DicosChips implements IChips{
public void eat(){
System.out.println("吃到了DicosChips....");
}
}
public interface IStore{
public IChips getChips();
}
public class Mcdonald implements IStore{
public IChips getChips(){
System.out.println("麦当劳生产了薯条....");
return new MCchips();
}
}
public class KFC implements IStore{
public IChips getChips(){
System.out.println("肯德基生产了薯条....");
return new KFCchips();
}
}
public class Dicos implements IStore{
public IChips getChips(){
System.out.println("德克士生产了薯条....");
return new DicosChips();
}
}
//场景类
public class Client{
public static void main(String[] args){
IStore store = new Dicos();
store.getChips().eat();
}
}
好了,先到这吧。欢迎大家关注我的微信公众号!!!

网友评论