介绍

将创建对象的具体过程屏蔽、隔离,从而达到更高的灵活性,工厂模式可以分为:简单工厂模式【Simple Factory】、工厂方法模式【Factory Method】、抽象工厂模式【Abstract Factory】;

简单工厂模式

定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可;

UML结构图
image.png

  1. 工厂类角色:该模式的核心,用来创建产品,含有一定的商业逻辑和判断逻辑;
  2. 抽象类产品角色:它一般是具体产品继承的父类或者实现的接口;
  3. 具体产品角色:工厂类所创建的对象就是此角色的实例,在Java中由一个具体类实现。

代码实现
产品类:

  1. abstract class BMW {
  2. public BMW(){}
  3. }
  4. public class BMW320 extends BMW {
  5. public BMW320() {
  6. System.out.println("制造-->BMW320");
  7. }
  8. }
  9. public class BMW523 extends BMW{
  10. public BMW523(){
  11. System.out.println("制造-->BMW523");
  12. }
  13. }

工厂类:

  1. public class Factory {
  2. public BMW createBMW(int type) {
  3. switch (type) {
  4. case 320:
  5. return new BMW320();
  6. case 523:
  7. return new BMW523();
  8. default:
  9. break;
  10. }
  11. return null;
  12. }
  13. }

客户端:

  1. public class Customer {
  2. public static void main(String[] args) {
  3. Factory factory = new Factory();
  4. BMW bmw320 = factory.createBMW(320);
  5. BMW bmw523 = factory.createBMW(523);
  6. }
  7. }

优缺点
优点:提供工厂类用于创建对象,实现了对象创建和使用的职责分离,客户端不需要知道所创建的具体产品类类名以及创建过程,只需要知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性;
缺点:不符合开闭原则,每次添加新产品就修改修改工厂类。在产品类型较多时,会造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作就会影响整个系统。

工厂方法模式

将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。

UML结构图
Image.png

  • 抽象工厂AbstrectFactory:工厂方法模式的核心,是具体工厂角色必须实现的接口或者必须继承的父类,在Java中由抽象类或者接口来实现;
  • 具体工厂Factory:被应用程序调用以创建具体产品的对象,含有具体业务逻辑相关的代码;
  • 抽象产品AbstractProduct:具体产品继承的父类或实现的接口,在Java中一般由抽象类或者是接口来实现;
  • 具体产品Product:具体工厂角色所创建的对象。

代码实现
产品类:

  1. abstract class BMW {
  2. public BMW(){}
  3. }
  4. public class BMW320 extends BMW {
  5. public BMW320() {
  6. System.out.println("制造-->BMW320");
  7. }
  8. }
  9. public class BMW523 extends BMW{
  10. public BMW523(){
  11. System.out.println("制造-->BMW523");
  12. }
  13. }

工厂类:

  1. interface FactoryBMW {
  2. BMW createBMW();
  3. }
  4. public class FactoryBMW320 implements FactoryBMW{
  5. @Override
  6. public BMW320 createBMW() {
  7. return new BMW320();
  8. }
  9. }
  10. public class FactoryBMW523 implements FactoryBMW {
  11. @Override
  12. public BMW523 createBMW() {
  13. return new BMW523();
  14. }
  15. }

客户类:

  1. public class Customer {
  2. public static void main(String[] args) {
  3. FactoryBMW320 factoryBMW320 = new FactoryBMW320();
  4. BMW320 bmw320 = factoryBMW320.createBMW();
  5. FactoryBMW523 factoryBMW523 = new FactoryBMW523();
  6. BMW523 bmw523 = factoryBMW523.createBMW();
  7. }
  8. }

抽象工厂模式

产品等级结构:产品等级结构指的是产品的继承结构,例如一个空调抽象类,有海尔空调、格力空调、美的空调等一系列子类,在这个空调抽象类和他的子类就构成一个产品等级结构;
产品足:产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。比如海尔工厂生产海尔空调、海尔冰箱,它们都来自不同 产品等级。
image.png

抽象工厂模式的定义
主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
但是在添加新的行为时比较麻烦,如果需要添加一个新产品族对象,需要变更接口以及旗下的所有子类,比较麻烦。

UML结构图:
Image.png

  • AbstractFactory:抽象工厂,提供创建产品的接口,包含多个创建产品的方法,可以创建多个不同等级的产品,里面包含所有产品创建的抽象方法;
  • ConcreteFactory:具体工厂,实现抽象工厂中的多个抽象方法,完成具体产品的创建;
  • Product:抽象产品,定义产品的规范,描述产品的主要特性和功能,完成具体产品的创建,可能会有两种不同的实现;
  • ConcreteProduct:具体的产品,主要实现抽象产品所定义的接口,由具体工厂来创建,同具体工厂之间是多对一的关系。

代码实现:使用不同的数据库【mysql、sqlserver】,对不同的数据表【user表、department表】进行数据的插入和获取;
Image.png

  • IFactory:抽象工厂,定义出创建具体产品的抽象产品;
    • SqlServerFactory:具体工厂,定义创建使用SqlServer的user和department产品;
    • MysqlFactory:具体工厂,定义创建使用Mysql的user和department产品;
  • IUser:抽象user产品,定义user相关的操作和特性;
    • SqlServerUser:SqlServer的user产品;
    • MySqlUser:MySql的user产品;
  • IDepartment:抽象department产品,定义department相关特性以及方法;
    • SqlServerDepartment:SqlServer的department产品;
    • MySqlDepartment:Mysql的department产品;

抽象工厂:

  1. /**
  2. * @author xulihua
  3. * @date 2021/1/18 11:10
  4. * 抽象工厂
  5. */
  6. public interface IFactory {
  7. /**
  8. * 创建user
  9. * @return
  10. */
  11. IUser createUser();
  12. /**
  13. * 创建department
  14. * @return
  15. */
  16. IDepartment createDepartment();

mysql工厂:

  1. /**
  2. * @author xulihua
  3. * @date 2021/1/18 11:20
  4. * mysql工厂
  5. */
  6. public class MySqlFactory implements IFactory {
  7. @Override
  8. public IUser createUser() {
  9. return new MySqlUser();
  10. }
  11. @Override
  12. public IDepartment createDepartment() {
  13. return new MySqlDepartment();
  14. }
  15. }

SqlServer工厂:

  1. /**
  2. * @author xulihua
  3. * @date 2021/1/18 11:18
  4. * sqlserver工厂
  5. */
  6. public class SqlServerFactory implements IFactory {
  7. @Override
  8. public IUser createUser() {
  9. return new SqlServerUser();
  10. }
  11. @Override
  12. public IDepartment createDepartment() {
  13. return new SqlServerDepartment();
  14. }
  15. }

抽象产品User:

  1. /**
  2. * @author xulihua
  3. * @date 2021/1/18 11:13
  4. * 抽象产品user
  5. */
  6. public interface IUser {
  7. /**
  8. * 插入数据
  9. * @param user
  10. */
  11. void insert(User user);
  12. /**
  13. * 获取数据
  14. * @param id
  15. * @return
  16. */
  17. User getOne(Integer id);
  18. }

抽象产品Department:

  1. /**
  2. * @author xulihua
  3. * @date 2021/1/18 11:14
  4. * 抽象产品department
  5. */
  6. public interface IDepartment {
  7. /**
  8. * 插入数据
  9. * @param department
  10. */
  11. void insert(Department department);
  12. /**
  13. * 获取数据
  14. * @param id
  15. * @return
  16. */
  17. Department getOne(Integer id);
  18. }

具体产品mysql族的User

  1. /**
  2. * @author xulihua
  3. * @date 2021/1/18 11:56
  4. * 具体user产品[mysql]
  5. */
  6. public class MySqlUser implements IUser {
  7. @Override
  8. public void insert(User user) {
  9. Common.addUser(user);
  10. System.out.println("MySql添加user数据:"+user);
  11. }
  12. @Override
  13. public User getOne(Integer id) {
  14. User user = Common.getUser(id);
  15. System.out.println("MySql获取id为"+id+"user数据:"+user);
  16. return user;
  17. }
  18. }

具体产品SqlServer的User

  1. /**
  2. * @author xulihua
  3. * @date 2021/1/18 11:20
  4. * 具体产品user[SqlServer]
  5. */
  6. public class SqlServerUser implements IUser{
  7. @Override
  8. public void insert(User user) {
  9. Common.addUser(user);
  10. System.out.println("插入user数据:"+user);
  11. }
  12. @Override
  13. public User getOne(Integer id) {
  14. User user = Common.getUser(id);
  15. System.out.println("获取id为"+id+"的user记录:"+user);
  16. return user;
  17. }
  18. }

具体产品mysql族的department

/**
* @author xulihua
* @date 2021/1/18 11:58
* 具体产品department[mysql]
*/
public class MySqlDepartment implements IDepartment {
    @Override
    public void insert(Department department) {
        Common.addDepartment(department);
        System.out.println("MySQL添加department数据"+department);
    }
    @Override
    public Department getOne(Integer id) {
        Department department = Common.getDepartment(id);
        System.out.println("MySQL获取id为"+id+"的department数据:"+department);
        return department;
    }
}

具体产品SqlServer的department

/**
* @author xulihua
* @date 2021/1/18 11:40
* 具体产品department[SqlServer]
*/
public class SqlServerDepartment implements IDepartment{
    @Override
    public void insert(Department department) {
       Common.addDepartment(department);
        System.out.println("SqlServer添加department数据:"+department);
    }
    @Override
    public Department getOne(Integer id) {
        Department department = Common.getDepartment(id);
        System.out.println("SqlServer获取id为"+id+"department数据:"+department);
        return department;
    }
}

客户端

/**
* @author xulihua
* @date 2021/1/18 12:04
*/
public class Client {
    public static void main(String[] args) {
        // mysql
        IFactory factory=new MySqlFactory();
        IUser user = factory.createUser();
        User u1= new User(44,"虎虎");
        user.insert(u1);
        user.getOne(44);
        // SqlServer
        // SqlServerFactory sqlServerFactory = new SqlServerFactory();
        // IDepartment department = sqlServerFactory.createDepartment();
        // Department dep = new Department(55, "技术部");
        // department.insert(dep);
        // department.getOne(55);
    }
}

工厂模式小结:
区别:
工厂方法只有一个抽象产品类和一个抽象工厂类,但可以派生出多个具体产品类和具体工厂类,每个具体工厂类只能创建一个具体产品类的实例;
抽象工厂模式拥有多个抽象产品类(产品族)和一个抽象工厂类,每个抽象产品类可以派生出多个具体产品类;抽象工厂类可以派生出多个具体工厂类,同时每个具体工厂类可以创建多个具体产品类的实例。