设计模式轻松学之02 工厂方法和简单工厂模式

前言

GOF( Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides)联合出版的书中提到的设计模式一共有23种,可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。

工厂模式的特点

这一章我们主要介绍创建型模式之工厂模式(Factory Pattern)。它的特点是,将对象的使用者和提供者进行隔离,从而达到解耦的作用。

比如我们在刚开始使用Java的时候,总会在代码里使用new关键字来创建对象,如果创建出来的对象要进行一系列的初始化操作,还需要我们自己来做。如果后期代码需要修改,则需要修改多处使用到了该对象的地方,因此出现了工厂模式。

工厂——顾名思义就是生产产品的地方,而Java中的工厂就是生产对象的地方。Java中的工厂通常是一个类或者对象,它提供一个接口来获取对象,例如Factory.getBean()。当然,这个Factory里的代码也是需要我们自己来写的~~

简单工厂模式

简单工厂模式不在23种设计模式之中,但是它是工厂模式的起点,而且应用范围也很广。

一个例子

由于某种原因,我们系统将用户分别存储在MySQL和Oracle数据库中了,根据不同的情况需要从两个数据库中取值。根据简单工厂模式,我们可以这样设计:

0. 工具类

用户类并不是我们工厂模式必须的,只是这个例子中用到的一个工具:

public class User {
    // 用户信息略...
}
1. 对象接口
public interface UserDao {
    // 根据用户名获取用户
    User getUser(String username);
    // 例如修改用户等其他方法略..
}
2. 业务类
  1. 连接MySQL数据库用的
public class MysqlUserDao implements UserDao {
    @Override
    public User getUser(String username) {
        // ..省略一些列操作
        System.out.println("使用Mysql数据库查找用户");
        return new User();
    }
}
  1. 连接Oracle数据库用的
public class OracleUserDao implements UserDao {
    @Override
    public User getUser(String username) {
        // ..省略一些列操作
        System.out.println("使用Oracle数据库查找用户");
        return new User();
    }
}
3. 工厂类
public class UserDaoFactory {
    public static UserDao getBean(String type) {
        if ("mysql".equals(type)) {
            return new MysqlUserDao();
        }
        if ("oracle".equals(type)) {
            return new OracleUserDao();
        }
        throw new RuntimeException("找不到对应的类型");
    }
}
4. 测试
// 需要连接MySQL数据库时
UserDao userDao = UserDaoFactory.getBean("mysql");
userDao.getUser("test");
// 需要连接MySQL数据库时
UserDao userDao1 = UserDaoFactory.getBean("oracle");
userDao1.getUser("test");
简单工厂模式总结:

首先,简单工厂模式通常用来生产某一类的对象,这些对象通常是某个接口的子类。所以我们需要先创建一个通用的接口,然后再创建实际的业务类。

其次,在工厂中我们提供一个静态方法,返回类型是接口的类型。根据工厂类静态方法中传入的不同字符串,返回具体的子类。

逻辑和过程都非常的简单,而且应用范围也很广。但是也有一定的缺陷,比如说如果传入的字符串拼错了怎么办?【这个可以通过维护一个常量来解决】还有就是如果需要增加子类,那么就需要修改工厂类中的代码。

工厂方法模式

按照刚才的业务和需求,我们这次使用工厂方法模式来解决。

0. 工具类

用户类并不是我们工厂模式必须的,只是这个例子中用到的一个工具:

public class User {
    // 用户信息略...
}
1. 对象接口
public interface UserDao {
    // 根据用户名获取用户
    User getUser(String username);
    // 例如修改用户等其他方法略..
}
2. 业务类
  1. 连接MySQL数据库用的
public class MysqlUserDao implements UserDao {
    @Override
    public User getUser(String username) {
        // ..省略一些列操作
        System.out.println("使用Mysql数据库查找用户");
        return new User();
    }
}
  1. 连接Oracle数据库用的
public class OracleUserDao implements UserDao {
    @Override
    public User getUser(String username) {
        // ..省略一些列操作
        System.out.println("使用Oracle数据库查找用户");
        return new User();
    }
}
3. 工厂类接口
public interface UserDaoFactory {
    UserDao getBean();
}
4. 为每个类型的业务类创建自己的工厂
  1. MysqlUserDao工厂
public class MysqlUserDaoFactory implements UserDaoFactory {
    @Override
    public UserDao getBean() {
        return new MysqlUserDao();
    }
}
  1. OracleUserDao工厂
public class OracleUserDaoFactory implements UserDaoFactory{
    @Override
    public UserDao getBean() {
        return new OracleUserDao();
    }
}
5.测试
// 创建工厂对象
MysqlUserDaoFactory mysqlUserDaoFactory = new MysqlUserDaoFactory();
// 获取业务类对象
UserDao userDao1 = mysqlUserDaoFactory.getBean();
userDao1.getUser("test");

// 创建工厂对象
OracleUserDaoFactory oracleUserDaoFactory = new OracleUserDaoFactory();
// 获取业务类对象
UserDao userDao2 = oracleUserDaoFactory.getBean();
userDao2.getUser("test");
工厂方法模式总结

工厂方法模式其实也比较简单。

  1. 为业务接口创建一个生产该接口的工厂接口

  2. 为每个业务类创建一个工厂,有多少个业务类就要创建多少个工厂

跟简单工厂模式的对比:

缺点:

结构上,工厂方法模式比简单工厂要复杂。

代码量上,由于每个业务类都需要创建属于自己的工厂,所以带么有不少的冗余。

优点:

如果需要新增业务类不用修改原来的代码,直接新增一个工厂即可。

那么使用哪一种比较好呢?通常使用简单工厂模式比较多,但是如果系统变化较快或者有其他原因,也可以选择使用工厂方法模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值