设计模式 简单工厂 工厂方法 抽象工厂

针对实体user,希望写一系列的功能,能够实现数据库的增删改查等功能。

    public static void main(String[] args) {
        User u = new User();
        u.setName("methol");

        add(u);
        edit(u);
    }
    
    public static void add(User user){
        System.out.println("save user【" + user.getName() + "】 to db");
    }
    
    public static void edit(User user){
        System.out.println("edit user【" + user.getName() + "】, and save to db");
    }

上面的方法虽然基本上实现了功能,但是不利于程序以后的扩展和复用,代码也不容易维护。
通过封装、继承、多态把程序的耦合度降低,使用设计模式可以使得程序更加灵活,后期容易修改,也更加易于复用。
有了如下的代码:

package mode.factory.simple;

import mode.factory.bean.User;

public interface Operation {

    void operate(User user);

}

package mode.factory.simple;

import mode.factory.bean.User;

public class AddOperate implements Operation {

    @Override
    public void operate(User user) {
        System.out.println("save user【" + user.getName() + "】 to db");
    }
}
package mode.factory.simple;

import mode.factory.bean.User;

public class EditOperate implements Operation {

    @Override
    public void operate(User user) {
        System.out.println("edit user【" + user.getName() + "】, and save to db");
    }
}
    public static void main(String[] args) {
        User u = new User();
        u.setName("methol");

        // 不同的操作需要new不同的类操作
        Operation addOperate = new AddOperate();
        addOperate.operate(u);
        Operation editOperate = new EditOperate();
        editOperate.operate(u);
    }

上述代码已经经过封装,并且也适合之后的代码扩展,但是还是有一个问题,如果后期想通过不同的参数(事先不知道是要执行edit还是add),那么就要通过条件判断要做的操作,这时简单工厂模式可能就是一个比较好的选择。

简单工厂模式与工厂模式

package mode.factory.simple;

public class OperateFactory {
    public static Operation findOperation(String operation) {
        switch (operation) {
            case "add":
                return new AddOperate();
            case "edit":
                return new EditOperate();
            default:
                return null;
        }
    }
}

通过工厂类来帮我们new一个对象,而不是直接在代码中需要的地方new一个对象,在同一个地方管理,后期的代码维护和扩展性都强了很多。
或者这时想增加一个delete方法,只需要继承Operation类,写一个方法,然后在OperateFactory增加一个case即可。
简单工厂模式,就是一个简单的创建产品(Operation)的工具,可以是AddOperate类,也可以是EditOperate类,甚至他们之间没有任何关系也是没问题的。
工厂模式,他也是一个简单的创建产品(Operation)的工具,但是他有一个区别是所有的产品(AddOperateEditOperate)都是继承(实现)Operation这个父类的,父类中有抽象的方法,之后都是调用同一个方法来做操作。
使用中,很少使用简单工厂模式,大多都是工厂模式,谈到工厂模式,基本上都是指的工厂模式。

    public static void main(String[] args) {
        User u = new User();
        u.setName("methol");

        // 不同的操作需要new不同的类操作
        Operation addOperate = new AddOperate();
        addOperate.operate(u);
        Operation editOperate = new EditOperate();
        editOperate.operate(u);

        // 使用一个简单的工厂,让工厂来帮我们选择
        OperateFactory.findOperation("add").operate(u);
        OperateFactory.findOperation("edit").operate(u);
    }

工厂方法

Operation做了一些小的修改,增加了一个方法

public interface Operation {

    void operate(User user);

    Operation createDefault(String operationType);
}
public class AddOperate implements Operation {

    @Override
    public void operate(User user) {
        System.out.println("save user【" + user.getName() + "】 to db");
    }

    @Override
    public Operation createDefault(String operationType) {
        return OperateFactory.findOperation(operationType);
    }
}
public class EditOperate implements Operation {

    @Override
    public void operate(User user) {
        System.out.println("edit user【" + user.getName() + "】, and save to db");
    }

    @Override
    public Operation createDefault(String operationType) {
        return OperateFactory.findOperation(operationType);
    }
}

工厂方法主要系是两个元素,产品(Operation)和创建者(OperateFactory)。
而工厂方法就是一个创建者这个类的一个方法而已,这个方法就是用来封装产品的创建。
和工厂模式的区别是,工厂模式的最大优点在于工厂类中包含了逻辑判断,根据(客户端)传入的参数动态实例化相关的类,那么对于客户端来说,他是不需要关心产品(Operation)的,他只需要关心传入的参数。而工厂模式这时把这一动作延后,接口定义了一个用来创建对象的接口,让子类决定实例化哪个类,工厂方法使一个类的实例化过程延迟到其子类。

抽象工厂

抽象工厂,顾名思义,就是对工厂进行抽象。
工厂方法和工厂模式都是对产品抽象封装,通过一个工厂,生产多种产品。
抽象工厂就是通过不同的工厂生产不同的产品。
还是上面的例子,OperateFactory创建了新增和修改两种操作(产品),此时有一个新的需求来了,之前用的数据库使mysql,现在想改成oracle,此时就对OperateFactory进行抽象。

package mode.factory.abstracs;

import mode.factory.bean.User;
import mode.factory.simple.Operation;

public interface Factory {

    void add(User user);

    void edit(User user);

    Operation createDefault(String operationType);
}

接口申明了,不管是申明工厂,都需要有add和edit这两种产品的生产。不同的接口只需要实现这个接口,做自己的操作即可。同时不同的工厂还可以实现自己独有的产品的生产。

package mode.factory.abstracs;

import mode.factory.bean.User;
import mode.factory.simple.Operation;

public class MysqlOperateFactory implements Factory {
    @Override
    public void add(User user) {
        createDefault("add").operate(user);
    }

    @Override
    public void edit(User user) {
        createDefault("edit").operate(user);
    }

    @Override
    public Operation createDefault(String operationType) {
        return new MysqlOperate().findOperation(operationType);
    }
}
package mode.factory.abstracs;

import mode.factory.bean.User;
import mode.factory.simple.Operation;

public class OracleOperateFactory implements Factory {
    @Override
    public void add(User user) {
        createDefault("add").operate(user);
    }

    @Override
    public void edit(User user) {
        createDefault("edit").operate(user);
    }

    @Override
    public Operation createDefault(String operationType) {
        return new OracleOperate().findOperation(operationType);
    }
}

这里也用了工厂方法的思想,抽象工厂的模式实现了工厂线的扩展。

小结

  1. 工厂模式就是一个类,它用来根据客户端(参数)具体的实例化某个对象。
  2. 工厂方法也是实例化对象,但是他把这个过程延迟到了子类,由子类决定具体实例化哪个对象。
  3. 抽象工厂是对工厂的扩展。他是在工厂方法的上面做的进一步的抽象。
  4. 工厂模式是用来生产产品的,不能增加产品;工厂方法是用来生产产品,同时也可以增加产品(实现接口,增加产品);抽象工厂用来增加工厂的,他不能增加产品。