谈谈工厂模式
工厂模式的作用
工厂模式有如下作用:
- 实现代码解耦,客户端只负责使用类的方法,类的实例化工作由工厂负责;
- 简化客户端获取类实例的过程,有些类的实例化过程较复杂,利用工厂可以将这一过程代码进行封装;
- 减少代码修改,使代码可复用。客户端可能多处实例化同一个类,如果实例化代码需要修改则只要修改工厂即可,这也意味着工厂是这些代码可复用,而不是每实例化一次就再写一份实例化代码。
三种工厂模式
接下来我将模拟用工厂模式实现使用不同数据库(mysql和mongodb)存储用户和查找用户信息。我们再设计程序的过程中常会遇到需求的改变,比如开始一个系统采用mysql来存储信息,而后来需要将mysql更换为mongodb,如果不对软件做精心的设计将迎来大量修改,导致代码BUG频出。
简单工厂模式
简单工厂模式代码如下,有如下特点:
- 需要switch逻辑判断;
- 每增加一个类需要在工厂内增加一个switch条件,违反开闭原则。
public class UserFactory { public static UserRepository createUser(String db) { UserRepository userRepository = null; switch (db) { case "mysql" : userRepository = new MysqlServerUser(); break; case "mongodb" : userRepository = new MongodbServerUser(); break; } return userRepository; } }
简单工厂模式的类图如下:

工厂方法模式
工厂方法模式是对简单工厂模式每增加一个类就需要修改工厂的问题进行了改进。
工厂方法模式为工厂增加了实现接口,每个类都需要实现自己的工厂,相比简单工厂模式只有一个工厂,工厂方法模式无疑会多出很多工厂,但是它解决了每增加一个类就需要修改工厂的问题。
工厂接口
public interface MethodFactory { UserRepository CreateUser(); }
不同的类都需要实现自己的工厂类
Mysql:
public class UserMysqlFactory implements MethodFactory { @Override public UserRepository CreateUser() { return new MysqlServerUser(); } }
MongoDB:
public class UserMongoFactory implements MethodFactory { @Override public UserRepository CreateUser() { return new MongodbServerUser(); } }
客户端应用
public class UserTest {
public static void main(String[] args) {
User user = new User();
user.setId(0);
user.setUserName("li");
user.setAge(18);
/* 如需要替换成MongoDB来存储,那么只需要将UserMysqlFactory修改为UserMongodbFactory即可 */
DBFactory dbFactory1 = new UserMysqlFactory();
UserRepository userRepository = dbFactory1.CreateUser();
userRepository.insert(user);
}
}
抽象工厂模式
抽象工厂模式其实与工厂方法模式代码结构类似,但是它是对工厂方法模式更深度的应用。抽象工厂不是针对某个类的工厂,而是多个类集合的工厂。
工厂接口
public interface AbstractFactory { UserRepository CreateUser(); DepartmentRepository CreateDepartment(); }
从工厂接口可以看出,抽象工厂除了创建User类外还负责创建Department类,如果是工厂方法模式我们就需要为Department单独创建一个工厂类。
因此抽象工厂可以看作是一个多个类集合的工厂。
总结
1.对于实例化较复杂的类,如mysql需要初始化前需要填入地址,用户名,密码等,可以使用工厂将代码进行封装,用户直接调用方法避免出错的问题。而对于实例化较简单的类不如直接new来得更简单。
2.对于类自身有很多子类的情况,使用工厂模式可以避免错误引用的问题。

浙公网安备 33010602011771号