设计模式在开发中的应用 -- 工厂模式

简单工厂

这个模式本身很简单而且使用在业务较简单的情况下。一般用于小项目或者具体产品很少扩展的情况(这样工厂类才不用经常更改)。 它由三种角色组成:
工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,根据逻辑不同,产生具体的工厂产品。如例子中的Driver类。
抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。如例中的Car接口。
具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现,如例子中的Benz、Bmw类。

工厂方法

工厂方法模式:有四个角色,抽象工厂模式,具体工厂模式,抽象产品模式,具体产品模式。不再是由一个工厂类去实例化具体的产品,而是由抽象工厂的子类去实例化产品

定义一个接口

public interface Moveable {
    void run();
}

两个实现类

public class Car implements Moveable {
    @Override
    public void run() {
        System.out.println("car...");
    }
}

public class Plane implements Moveable {
    @Override
    public void run() {
        System.out.println("Plane...");
    }
}

定义一个抽象工厂

public abstract class VehicleFactory {
    abstract Moveable create();
}

两个具体工厂

public class PlaneFactory extends VehicleFactory {
    @Override
    Moveable create() {
        return new Plane();
    }
}

public class CarFactory extends VehicleFactory
{
    @Override
    Moveable create() {
        return new Car();
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        VehicleFactory factory = new CarFactory();
        Moveable moveable = factory.create();
        moveable.run();
    }
}

运行结果
在这里插入图片描述

抽象工厂

提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。
与工厂方法模式不同的是,工厂方法模式中的工厂只生产单一的产品,而抽象工厂模式中的工厂生产多个产品

一个login和user实体类

@Data
@ToString
public class User {
    private int id;
    private String username;
    private String password;
}

@Data
@ToString
public class Login {
    private int id;
    private Date date;
}

定义三个接口

public interface IFactory {
    IUser createUser();
    ILogin createLogin();
}
public interface ILogin {
    void insert(Login login);
    Login getLogin(int id);
}
public interface IUser {
    void insert(User user);
    IUser getUser(int uid);
}

两个具体工厂

public class MysqlFactory implements IFactory {
    @Override
    public IUser createUser() {
        return new MysqlUser();
    }

    @Override
    public ILogin createLogin() {
        return new MysqlLogin();
    }
}
public class OracleFactory implements IFactory {
    @Override
    public IUser createUser() {
        return new OracleUser();
    }

    @Override
    public ILogin createLogin() {
        return new OracleLogin();
    }
}

具体的产品

public class MysqlLogin implements ILogin {
    @Override
    public void insert(Login login) {
        System.out.println("对 MySQL 里的 Login 表插入了一条数据");
    }

    @Override
    public Login getLogin(int id) {
        System.out.println("通过 uid 在 MySQL 里的 Login 表得到了一条数据");
        return null;
    }
}
public class MysqlUser implements IUser {
    @Override
    public void insert(User user) {
        System.out.println("对 MySQL 里的 user 表插入了一条数据");
    }

    @Override
    public IUser getUser(int uid) {
        System.out.println("通过 uid 在 MySQL 里的 user 表得到了一条数据");
        return null;
    }
}
public class OracleLogin implements ILogin {
    @Override
    public void insert(Login login) {
        System.out.println("对 Oracle 里的 Login 表插入了一条数据");
    }

    @Override
    public Login getLogin(int id) {
        System.out.println("通过 uid 在 Oracle 里的 Login 表得到了一条数据");
        return null;    }
}
public class OracleUser implements IUser {

    @Override
    public void insert(User user) {
        System.out.println("对 Oracle 里的 user 表插入了一条数据");
    }

    @Override
    public IUser getUser(int uid) {
        System.out.println("通过 uid 在 Oracle 里的 Login 表得到了一条数据");
        return null;
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        User user = new User();
        Login login = new Login();

        // 只需要确定实例化哪一个数据库访问对象给factory
        IFactory factory = new MysqlFactory();

        // 已与具体的数据库访问解除了耦合
        IUser user1 = factory.createUser();
        user1.getUser(1);
        user1.insert(user);

        ILogin login1 = factory.createLogin();
        login1.getLogin(1);
        login1.insert(login);
    }
}

运行结果
在这里插入图片描述

从客户端的代码中,我们只需要更改 IFactory factory=new MysqlFactory(); 为 IFactory factory=new OracleFactory();,就实现了数据库访问的切换。而且实际上我们这次代码的重构已经使用到了抽象工厂模式,抽象工厂可能表面上看起来貌似与工厂方法模式没什么区别,其实不然,所以我之前才说抽象工厂模式是基于工厂方法模式的。

只有一个User表的封装类和User表的操作类时,我们只用到了工厂方法模式,而且也只需要使用到工厂方法模式。但是显然现在我们的数据库已经不止一个User表了,而 MySQL 和 Oracle 又是两大不同的分类,所以解决这种涉及到多个产品系列的问题,就需要使用到专门解决这种问题的模式:抽象工厂模式。这时候再回过头去看DP对抽象工厂模式的定义就不难理解了。

所以抽象工厂与工厂方法模式的区别在于:抽象工厂是可以生产多个产品的,例如 MysqlFactory 里可以生产 MysqlUser 以及 MysqlLogin 两个产品,而这两个产品又是属于一个系列的,因为它们都是属于MySQL数据库的表。而工厂方法模式则只能生产一个产品,例如之前的 MysqlFactory 里就只可以生产一个 MysqlUser 产品。

猜你喜欢

转载自blog.csdn.net/zhouhaihua57410/article/details/82827685