前言
本章讲解Java中工厂设计模式的相关概念
方法
1.概念
所谓的工厂,我们可以理解其为一个生产车间。之前我们需要实例化对象的时候都要使用new关键字,这种方式使得调用者和创建者耦合在了一起,不利于程序的维护与扩展。
使用工厂设计模式,以前new实例化对象的操作有我们的工厂方法代替,将选择实现类、创建对象统一管理和控制,从而将调用者和我们的实现类解耦。
2.工厂设计模式的类别
在讲解几种工厂设计模式的设计思路之前,我们先来看一下不运用工厂设计模式的情况。
创建工程如下:
其中,People是一个接口,有一个方法say(),Student、Teacher、Worker都实现了这个接口,并且重写了该say()方法。
Test是一个测试类,代码如下:
package cn.edu.ccut;
public class Test {
public static void main(String[] args) {
People student = new Student();
People teacher = new Teacher();
People worker = new Worker();
student.say();
teacher.say();
worker.say();
}
}
运行结果如下:
我们可以发现,调用者Test必须知道接口People以及其三个实现类,耦合度相当的大。同时也不利于后期的扩展。
为了解决上述问题,我们引入了工厂设计模式!
1)简单工厂模式(简单、常用)
在上面的工程基础上我们添加一个工厂类PeopleFactory:
package cn.edu.ccut;
public class PeopleFactory {
public static People getInstance(String type){
if("student".equals(type)){
return new Student();
}else if ("teacher".equals(type)) {
return new Teacher();
}else if ("worker".equals(type)) {
return new Worker();
}else {
return null;
}
}
}
我们根据传入的类别来判断创建的对象,岂不是很完美!
修改Test类如下:
package cn.edu.ccut;
public class Test {
public static void main(String[] args) {
People student = PeopleFactory.getInstance("student");
People teacher = PeopleFactory.getInstance("teacher");
People worker = PeopleFactory.getInstance("worker");
student.say();
teacher.say();
worker.say();
}
}
那么这样的话,调用者无需知道具体的实现类细节,只需要知道其对应的接口就好了,达到了解耦的目的。
但是,我们仍然发现,如果该接口的实现类增多的话,那么就会无限的if...else...!
为了能让程序结构完美一些,我们也可以使用下面的方式,修改工厂类如下:
package cn.edu.ccut;
public class PeopleFactory {
public static People getStudentInstance(){
return new Student();
}
public static People getTeacherInstance(){
return new Teacher();
}
public static People getWorkerInstance(){
return new Worker();
}
}
2)工厂方法模式
该方式可以算作简单工厂模式的升级版,但使用上也不如简单工厂模式,实际也不是很推荐使用。
为了避免简单工厂模式在一个工厂中添加逻辑或者方法,我们将工厂类抽象化,由具体的实现类工厂负责专门的实例创建。
创建工厂接口类:PeopleFactory
package cn.edu.ccut;
public interface PeopleFactory {
public People getInstance();
}
分别创建学生、老师、工人的工厂类,其中学生工厂类代码如下:
package cn.edu.ccut;
public class StudentFactory implements PeopleFactory {
@Override
public People getInstance() {
return new Student();
}
}
那么我们编写测试类Test如下:
package cn.edu.ccut;
public class Test {
public static void main(String[] args) {
People student = new StudentFactory().getInstance();
People teacher = new TeacherFactory().getInstance();
People worker = new WorkerFactory().getInstance();
student.say();
teacher.say();
worker.say();
}
}
但是,由于其工程代码量的原因,该种方式一直被诟病。