工厂模式的核心就是实现创造者和调用者的分离
什么意思呢?举个栗子:我们想要买车的时候,会有奔驰,宾利等多种选择,但是我们该怎么实现呢?一般情况下,我们会使用多态的方式,如下:
public interface CarDemo {
public void car();
}
class Benz implements CarDemo {
@Override
public void car() {
System.out.println("Benz...");
}
}
class Bentley implements CarDemo {
@Override
public void car() {
System.out.println("Bentley...");
}
}
public class Main {
public static void main(String[] args) {
CarDemo car1 = new Benz();
CarDemo car2 = new Bentley();
}
}
但是,我们会发现,在进行测试的时候,我们涉及到了很多东西,既需要知道接口,还需要知道所有的实现类。但是我们真实情况下我们想要买一辆车,并不需要自己去new去创造,只需要知道名字,然后直接去工厂买就可以了,于是就有了工厂模式。
想要消费者更加便捷,那么我们需要把内部的细节交给工厂实现,仍然以车为例,其示意图如下:
从图中我们可以看到,Car是抽象类,有三个具体实现类,随后,Factory工厂类对于具体类进行细节操作,用户只需要再工厂类中调用即可。
public class Car {
}
public class Benz extends CarFactory {
public Benz() {
System.out.println("Benz...");
}
}
public class Bentley extends CarFactory {
public Bentley() {
System.out.println("Bentley...");
}
}
public class CarFactory {
//工厂类实现根据条件获取车的细节,根据名字获取即可
public Car getBenz() {
return new Benz();
}
public Car getBentley() {
return new Bentley();
}
}
public static void main(String[] args) {
//按名字获取即可
CarFactory.getBentley();
}
这样,我们就实现了工厂实现细节,消费者只需要知道名字就可以买车的操作
由于所有的方法都是静态的,直接调用即可,因此也被成为静态工厂模式,但是弊端也很明显,每次增加一辆新车的时候,都需要改动在CarFactory中的代码,那么后期想要增删改时将不好维护。
想要减少代码的耦合度,那么就有了工厂方法模式。
这种模式相较于简单工厂模式,更容易进行横向扩展。它对于每个车的类型都多加了自己的工厂,然后自己的工厂又实现了总工厂,图解如下:
这样的话,我们每增加一个类,如特斯拉,只需要重新写子类就可以了,代码示例如下:
public interface Car {
public void getName();
}
public class Bentley implements Car {
@Override
public void getName() {
System.out.println("Bentley...");
}
}
public interface CarFactory {
public Car getCar();
}
public class BentleyFactory implements CarFactory {
@Override
public Car getCar() {
return new Bentley();
}
}
public static void main(String[] args) {
Car car = new BentleyFactory().getCar();
car.getName();
}
测试结果:
这样的模式,我们如果有新增产品,只需要新增车类和车工厂类就可以了。
但是,如果有很多的不同的车呢?如果有100辆不同的车,那么就需要创建100个车及其工厂,这类就太膨胀了。
抽象工厂模式,实际上与产品产业链是比较相似的,比如华为与小米,它们分别都会有手机产业和路由器产业,产业相同但是厂家不同,图解如下:
那么,抽象工厂如何去实现呢?
首先,需要创建手机接口与路由器接口
//手机接口,有打电话,发短信,拍照功能
public interface Phone {
void call();
void message();
void camera();
}
//路由器接口,设置项有启动,关闭,开WiFi
public interface Router {
void start();
void shutDown();
void openWifi();
}
因为品牌的不同,因此不同品牌的东西是其具体类的实现
public class HuaweiPhone implements Phone {
@Override
public void call() {
System.out.println("华为来电");
}
@Override
public void message() {
System.out.println("华为短信");
}
@Override
public void camera() {
System.out.println("华为相机");
}
}
public class HuaweiRouter implements Router {
@Override
public void start() {
System.out.println("启动华为路由器");
}
@Override
public void shutDown() {
System.out.println("关闭华为路由器");
}
@Override
public void openWifi() {
System.out.println("打开华为WiFi");
}
}
public class XiaomiPhone implements Phone {
@Override
public void call() {
System.out.println("小米来电");
}
@Override
public void message() {
System.out.println("小米短信");
}
@Override
public void camera() {
System.out.println("小米相机");
}
}
public class XiaomiRouter implements Router {
@Override
public void start() {
System.out.println("开启小米路由器");
}
@Override
public void shutDown() {
System.out.println("关闭小米路由器");
}
@Override
public void openWifi() {
System.out.println("打开小米WiFi");
}
}
如何创建这些产品呢?于是引入工厂类,首先创建抽象工厂类,对于产品进行创造
//抽象产品工厂
public interface Factory {
//生产手机
Phone productPhone();
//生产路由器
Router productRouter();
}
随后,不同的厂家对于抽象接口进行实现。
public class HuaweiFactory implements Factory {
@Override
public Phone productPhone() {
return new HuaweiPhone();
}
@Override
public Router productRouter() {
return new HuaweiRouter();
}
}
public class XiaomiFactory implements Factory {
@Override
public Phone productPhone() {
return new XiaomiPhone();
}
@Override
public Router productRouter() {
return new XiaomiRouter();
}
}
这样,整个抽象工厂的创建就完成了,我们来进行一下校验:
public class Main {
public static void main(String[] args) {
//使用华为手机拍照
new HuaweiFactory().productPhone().camera();
//打开小米路由器的WiFi
Router router = new XiaomiFactory().productRouter();
router.start();
router.openWifi();
router.shutDown();
}
}
以上,就是三种工厂模式的概念与简单实现,其都有自己的优缺点。
方式二虽然实现了代码的解耦合,但是往往实际当中我们并不去使用这种模式,而是大量使用了看似不太好维护的方式一,方式三则是在有稳定的产业链时应用会更有效率。