java工厂设计模式个人浅析

1. 介绍

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。它的主要作用就是用来生产对象,将对象的创建和使用分开,降低了代码之间的耦合性。下面就以一些简单的代码来浅析工厂模式,加深对工厂模式的理解。这是我写的第一篇博客,才疏学浅,不足之处还望见谅。

2. 代码引入

下面以常见的用户注册登录代码为例。

userDao.java

public interface UserDao {
    //注册
    public void register();
    //登录
    public void login();
}

userDaoImpl.java

public class UserDaoImpl implements UserDao{
    @Override
    public void register() {
        System.out.println("insert user into table");
    }
    @Override
    public void login() {
        System.out.println("select username,pwd from table");
    }
}

userService.java

public interface UserService {
    public void register();
    public void login();
}

userServiceImpl.java

public class UserServiceImpl implements UserService{
    private UserDao userDao = new UserDaoImpl();

    @Override
    public void register() {
        userDao.register();
    }
    @Override
    public void login() {
        userDao.login();
    }
}

Test.java

public class Test {
    public static void main(String[] args) {
        UserService service = new UserServiceImpl();
        service.register();
        service.login();
    }
}

运行结果:

insert user into table
select username,pwd from table

3. 分析

上述代码在功能实现上没有什么问题,但存在耦合性,就是对象的创建和使用耦合在了一起。至于为什么要使用工厂模式解耦,可以看看这篇博客为什么要用工厂模式,我觉得讲的不错。这里主要讲解代码实现工厂模式。那接下来,我们将上述代码一步步改造成工厂模式。

4. 创建工厂类

既然我们要把对象的创建和使用分开,我们自然会想到创建一个工厂类。于是我们可以创建一个BeanFactory类,用于生产对象。

BeanFactory.java

public class BeanFactory {
    public static UserService getUserService(){
        return new UserServiceImpl();
    }
}

我们在工厂类里面定义了一个生产UserService类的方法,然后我们在主函数中通过BeanFactory调用此方法创建对象。

public class Test {
    public static void main(String[] args) {
        //UserService service = new UserServiceImpl();
        UserService service = BeanFactory.getUserService();
        service.register();
        service.login();
    }
}

最终结果是一样的:

insert user into table
select username,pwd from table

在上述代码中,我们不再直接通过new关键字创建对象,而是交给了BeanFactory类,让这个类创建我们需要的对象,实现了对象的创建和使用分离。不过,我们还是在工厂类的方法里new了对象,那么我们接下来可以对工厂类中创建对象的方法再进行改造。

5. 使用反射

学过反射应该知道,我们还可以通过反射创建对象,降低耦合;于是改造如下:

public class BeanFactory {
    public static UserService getUserService(){
        //return new UserServiceImpl();
        UserService service = null;
        try {
            Class clas = Class.forName("com.qiming.spring.service.UserServiceImpl");
            //创建对象
            service = (UserService) clas.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return service;
    }
}

上述代码改造后,我们只要输入要创建的对象的全限定类名,然后通过反射创建对象。

6. 简单工厂模式

上述代码中全限定类名作为一个字符串,还是需要我们在代码中写。那我们不妨将这个类名写在配置文件中,然后让代码读取配置文件,实现读写分离,进一步降低耦合。

创建一个配置文件 applicationContext.properties

userService = com.qiming.spring.service.UserServiceImpl

改造工厂类:

public class BeanFactory {
    /**
     * 通过properties类获取配置文件中的配置
     */
    private static Properties properties = new Properties();

    static {
        try {
            //1. 获得IO输入流
            InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("applicationContext.properties");
            //2. 加载流
            properties.load(inputStream);
            //3. 关闭流
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static UserService getUserService(){
        //return new UserServiceImpl();
        UserService service = null;
        try {
            //Class clas = Class.forName("com.qiming.spring.service.UserServiceImpl");
            Class clas = Class.forName(properties.getProperty("userService"));
            service = (UserService) clas.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return service;
    }
}

改造后,我们只需要修改配置文件里面的内容就可以修改对象,实现了读写分离。例如我们不再使用userServiceImpl对象时,而是使用userServiceNew时,我们只需要在配置文件中修改全限定类名即可:

userService = com.qiming.spring.service.UserServiceNew

这样极大降低了代码间的耦合,这就是一个简单的工厂模式。

7. 通用工厂模式

简单工厂模式极大降低了代码间的耦合,但实际中创建的对象不止一种。当我们要创建UserDao对象时,我们要写public static UserDao getUserDao()方法;要创建TextService对象时,要写public static TextService getTextService()方法…而且我们发现这些代码实现的过程基本是一样的,内容上具有重复性。所以,我们还可以继续改造工厂类里面的方法,用一个方法创建任意的对象。

public static Object getBean(String key){
        Object obj = null;
        try {
            Class cls = Class.forName(properties.getProperty(key));
            obj = cls.newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        return obj;
    }

当我们需要创建对象时,如下即可:

//创建UserService对象
UserService service = (UserService)BeanFactory.getBean("userService");
//创建UserDao对象
UserDao userDao = (UserDao)BeanFactory.getBean("userDao");
//创建TextService对象
TextService textService = (TextService)BeanFactory.getBean("textService");

这就是一个通用工厂模式。

8. 总结

通过上述一步步改造,我们实现了工厂模式。可以发现,我们写的通用工厂类有spring的内味了。没错,spring中的工厂类的实现思想和我们写的是差不多的,如spring中通过ApplicationContext获取容器对象,通过getBean读取创建对象… …spring可谓是工厂模式的设计典范,值得深入研究。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值