一、什么是工厂模式?
工厂模式是最常用的设计模式之一,它提供了一种创建对象的最佳方式,可以实现对象创建者和调用者的解耦。
二、工厂模式的三种类型
1.简单工厂模式
定义:定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。
案例:假设有这么一种情况,如果我需要买一辆车,可选择的有宝马和奥迪两类。首先我们实现一个 Car 的接口,接口声明一个name方法:
public interface Car {
void name();
}
写一个奥迪类和宝马类,都实现Car接口,并重写name方法:
public class Audi implements Car{
@Override
public void name() {
System.out.println("奥迪汽车");
}
}
public class BMW implements Car {
@Override
public void name() {
System.out.println("宝马汽车");
}
}
如果不使用工厂模式,我们要得到这两辆车的实例,就需要进行new操作,这样会增强代码的耦合性,不利于后期的扩展和维护,并且暴露创建逻辑。如果类的构造函数中含有大量参数,还给创建实例对象增加了难度。
public class Client {
public static void main(String[] args) {
BMW bmw = new BMW();
Audi audi = new Audi();
bmw.name();
audi.name();
}
}
而如果采用简单工厂模式,相当于在Client类和汽车类中加了一层工厂层,实现了对创建对象方法的封装,客户不需要知道创建对象的具体逻辑,只需要调用工厂的方法就可以:
public class CarFactory {
//方法一
public static Car getCar(String name){
if(name.equals("宝马")){
return new BMW();
}
if(name.equals("奥迪")){
return new Audi();
}else{
return null;
}
}
//方法二
public static Car getBMWCar(){
return new BMW();
}
public static Car getAudiCar(){
return new Audi();
}
}
public class Client {
public static void main(String[] args) {
//创建工厂对象
CarFactory carFactory = new CarFactory();
//方法一:
Car bmw = carFactory.getCar("宝马");
Car audi = carFactory.getCar("奥迪");
//方法二:
Car bmw2 = carFactory.getBMWCar();
Car audi2 = carFactory.getAudiCar();
bmw.name();
audi.name();
}
}
业务逻辑:
缺点:只有一个工厂类,如果需要创建的对象比较多,会使得这个工厂类的逻辑非常复杂。并且如果后期扩展了更多的业务,比如说多了一个奔驰类,那么我们就需要对工厂类的代码进行修改,这样就违背了面向对象的开闭原则,即***软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的***。
而为了改善这种缺点带来的弊端,就有了下面的工厂方法模式。
2.工厂方法模式
定义:定义一个用于创建产品对象的工厂的接口,将实际创建工作推迟到工厂接口的子类中。属于简单工厂模式的进一步抽象和推广。
案例:还是上面的例子,我们Car接口、宝马类和奥迪类都不变。创建一个工厂接口,声明一个getCar方法:
public interface CarFactory {
Car getCar();
}
创建一个宝马工厂类和奥迪工厂类,都实现CarFactory接口:
public class BMWFactory implements CarFactory {
@Override
public Car getCar() {
return new BMW();
}
}
public class AudiFactory implements CarFactory {
@Override
public Car getCar() {
return new Audi();
}
}
客户得到宝马和奥迪实例:
public class Client {
public static void main(String[] args) {
Car bmw = new BMWFactory().getCar();
Car audi = new AudiFactory().getCar();
bmw.name();
audi.name();
}
}
业务逻辑:
这样就很好的解决了业务横向扩展的问题,如果需要扩展业务,只需要增加几个业务类,不需要对原有的代码进行修改,很好的满足了开闭原则。
工厂方法模式是工厂模式家族中用的最多的。
3.抽象工厂模式
定义:抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。它适合有多个抽象角色时使用的一种工厂模式,即适合一家工厂生产一系列产品的情况。
案例:对于两类产品,比如说手机和路由器,但是又有两个工厂,一个是华为工厂,一个是小米工厂,每个工厂都能创建手机和路由器这两个产品。
创建手机和路由器接口:
public interface Phone {
void call();
}
public interface Router {
void startWifi();
}
创建华为手机、小米手机、华为路由器、小米路由器,分别实现对应的接口:
public class HuaweiPhone implements Phone {
@Override
public void call() {
System.out.println("华为手机可以打电话");
}
}
public class XiaomiPhone implements Phone{
@Override
public void call() {
System.out.println("小米手机可以打电话");
}
}
public class HuaweiRouter implements Router {
@Override
public void startWifi() {
System.out.println("华为路由器打开wifi");
}
}
public class XiaomiRouter implements Router {
@Override
public void startWifi() {
System.out.println("小米路由器打开wifi");
}
}
生成抽象工厂接口,即对小米工厂和华为工厂的抽象:
public interface ProductFactory {
Phone phoneFactory();
Router routerFactory();
}
创建小米工厂和华为工厂,并实现抽象工厂接口:
public class XiaomiFactory implements ProductFactory {
@Override
public Phone phoneFactory() {
return new XiaomiPhone();
}
@Override
public Router routerFactory() {
return new XiaomiRouter();
}
}
public class HuaweiFactory implements ProductFactory {
@Override
public Phone phoneFactory() {
return new HuaweiPhone();
}
@Override
public Router routerFactory() {
return new HuaweiRouter();
}
}
客户拿到拿到对象:
public class Client {
public static void main(String[] args) {
//华为产品
HuaweiFactory huaweiFactory = new HuaweiFactory();
Phone huaweiPhone = huaweiFactory.phoneProduct();
Router huaweiRouter = huaweiFactory.routerProduct();
huaweiPhone.call();
huaweiRouter.startWifi();
//小米产品
XiaomiFactory xiaomiFactory = new XiaomiFactory();
Phone xiaomiPhone = xiaomiFactory.phoneProduct();
Router xiaomiRouter = xiaomiFactory.routerProduct();
xiaomiPhone.call();
xiaomiRouter.startWifi();
}
}
业务逻辑:
抽象工厂模式适合一个工厂类中需要创建一系列产品,即产品族的情况。