工厂模式的主要作用就是实现了创建者和调用者的分离。
一、面向对象设计的基本原则
-
OCP
(开闭原则,Open-Closed Principle
):一个软件的实体应当对扩展开放,对修改关闭。 -
DIP
(依赖反转原则,Dependency Inversion Principle
):要针对接口编程,不要针对实现编程 -
LoD
(迪米特法则,Law of Demeter
):只与你直接的朋友通信,而避免和陌生人通信
二、应用场景
-
JDK
中Calendar
的getInstance
方法 -
JDBC
中Connection
对象的获取 -
Hibernate
中SessionFactory
创建Session
-
Spring
中IOC
容器创建管理bean
对象 -
XML
解析时DocumentBuilderFactory
创建解析器对象 - 反射中
Class
对象的newInstance
方法
三、详细分类
3.1 一般情况下
Car.java
package cn.itcast.day229.factory;
public interface Car {
public void run();
}
Audi.java
package cn.itcast.day229.factory;
public class Audi implements Car {
public void run() {
System.out.println("奥迪汽车");
}
}
Benz.java
package cn.itcast.day229.factory;
public class Benz implements Car {
public void run() {
System.out.println("奔驰汽车");
}
}
说明:这里有一个Car
接口,其有两个实现,一个是Audi
,一个是Benz
。当我们在不使用工厂的时候要用到这两个实现的时候需要这样,如下:
Client01.java
package cn.itcast.day229.factory;
//测试在不使用工厂模式的情况下,下面这个类就是调用者
//在使用的时候我们需要知道如何实例化对象,如果更复杂的情况就是实例化很麻烦的时候
//我们在使用的时候就很不方便,而且和各个子类耦合较紧,不利于扩展
public class Client01 {
public static void main(String[] args) {
Car c1 = new Audi();
Car c2 = new Benz();
c1.run();
c2.run();
}
}
说明:如上,可以看到我们必须要了解各个实现的具体方法,必须自己手工进行实例化,这样显然比较麻烦,下面我们看使用工厂的情况。
3.2 简单工厂模式(静态工厂模式)
用来生产同一等级结构中的任意产品(对于新增的产品,需要修改已有的代码)
SimpleCarFactory01.java
package cn.itcast.day229.factory;
//使用简单工厂模式,当然在后面如何我们想要扩展可能会需要修改一定的代码,所以简单工厂是有一点问题的
//但有时候这可以忽略(违背了开闭原则)
public class SimpleCarFactory01 {
public static Car createCar(String type) {
if ("奥迪".equals(type)) {
return new Audi();
} else if ("奔驰".equals(type)) {
return new Benz();
} else {
return null;
}
}
}
Client02.java
package cn.itcast.day229.factory;
//简单工厂情况下,此时我们就不需要和相关的实现关联了
public class Client02 {
public static void main(String[] args) {
Car c1 = SimpleCarFactory01.createCar("奥迪");
Car c2 = SimpleCarFactory01.createCar("奔驰");
c1.run();
c2.run();
}
}
说明:可以看到如果我们使用了简单工厂模式,在使用的时候无须了解各个实现的详细方法,也无须了解实现类的具体实现。只需要使用工厂为我们生产我们需要的实例对象即可。当然简单工厂还有另一种实现方式,实质差不多,如下:
SimpleCarFactory02.java
package cn.itcast.day229.factory;
//第二种简单工厂模式,其实两种都差不多
public class SimpleCarFactory02 {
public static Car createAudi(){
return new Audi();
}
public static Car createBenz(){
return new Benz();
}
}
说明:这种实现的本质和之前的类似。但是简单工厂实现虽然用的较多,但是当我们要扩展对象实现的时候就需要对工厂内部代码进行相关的修改,所以这破坏了设计的开闭原则,当然有时候可以忽略。
3.2 工厂方法模式
用来生产同一等级结构中的固定产品(支持增加任意产品)。为了避免简单工厂模式的缺点,不完全满足OCP
。工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。但是一般情况下我们还是使用简单工厂模式。
FactoryMethodCarFactory.java
package cn.itcast.day229.factory;
//工厂方法模式
public interface FactoryMethodCarFactory {
public Car createCar();
}
说明:这里我们创建一个工厂的接口,然后为每个类的创建实现一个对应的工厂,由各个单独的工厂来完全各个实例。
BenzFactory.java
package cn.itcast.day229.factory;
public class BenzFactory implements FactoryMethodCarFactory {
public Car createCar() {
return new Benz();
}
}
AudiFactory.java
package cn.itcast.day229.factory;
public class AudiFactory implements FactoryMethodCarFactory {
public Car createCar() {
return new Audi();
}
}
Client03.java
package cn.itcast.day229.factory;
//使用工厂方法模式
public class Client03 {
public static void main(String[] args) {
Car c1 = new AudiFactory().createCar();
c1.run();
}
}
说明:可以看到我们需要相关类的实例的时候是使用各个对应的工厂去完成的,这里将工厂进行了区分,当然如果我们要对实现进行扩展就不会破坏设计原则了。如下:
Byd.java
package cn.itcast.day229.factory;
//增加一个比亚迪车,此时我们不需要修改其他代码,只需要增加一个比亚迪汽车工厂即可。
public class Byd implements Car {
public void run() {
System.out.println("比亚迪汽车");
}
}
BydFactory.java
package cn.itcast.day229.factory;
public class BydFactory implements FactoryMethodCarFactory {
@Override
public Car createCar() {
return new Byd();
}
}
说明:可以看到这样我们就进行了扩展,无须对原来工厂中的方法中代码进行修改,这当然更好,但是维护起来却更复杂了。
3.3 抽象工厂模式
用来生产不同产品族的全部产品(对于新增的产品,无能为力,支持增加产品族)。是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种很好的解决方式。之前的情况是有一个接口和多个实现,但是有一种情况是有多个接口,每个接口又有多个实现,此时我们需要使用抽象工厂模式来解决。
例子:这里有发动机、座椅、轮胎三个产品族,也就是三个接口。而每个接口下面分别有高端和低端的实现,对于低端和高端的实现我们可以跟根据情况进行组合。
Engine.java
package cn.itcast.day231.AbstractFactory;
public interface Engine {
public void run();
public void start();
}
//高端发动机
class LuxuryEngine implements Engine{
@Override
public void run() {
System.out.println("好发动机速度快");
}
@Override
public void start() {
System.out.println("好发动机启动快");
}
}
//低端发动机
class LowEngine implements Engine{
@Override
public void run() {
System.out.println("差发动机速度慢");
}
@Override
public void start() {
System.out.println("差发动机启动慢");
}
}
Seat.java
package cn.itcast.day231.AbstractFactory;
//座椅接口
public interface Seat {
public void nice();
}
//高端座椅
class LuxurySeat implements Seat{
@Override
public void nice() {
System.out.println("高端座椅舒适度高");
}
}
//低端座椅
class LowSeat implements Seat{
@Override
public void nice() {
System.out.println("低端座椅舒适度低");
}
}
Tyre.java
package cn.itcast.day231.AbstractFactory;
//轮胎
public interface Tyre {
public void revole();
}
//高端轮胎
class LuxuryTyre implements Tyre{
@Override
public void revole() {
System.out.println("高端轮胎防滑性好");
}
}
//低端轮胎
class LowTyre implements Tyre{
@Override
public void revole() {
System.out.println("低端轮胎防滑性差");
}
}
说明:上面给出了几个产品族,也就是一辆汽车必须需要引擎、座椅、轮胎三类对象,我们需要工厂来创建一个实例对象。
LowCarFactory.java
package cn.itcast.day231.AbstractFactory;
//低端汽车工厂
public class LowCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new LowEngine();
}
@Override
public Seat createSeat() {
return new LowSeat();
}
@Override
public Tyre createTyre() {
return new LowTyre();
}
}
LuxuryCarFactory.java
package cn.itcast.day231.AbstractFactory;
//高端汽车工厂
public class LuxuryCarFactory implements CarFactory {
@Override
public Engine createEngine() {
return new LuxuryEngine();
}
@Override
public Seat createSeat() {
return new LuxurySeat();
}
@Override
public Tyre createTyre() {
return new LuxuryTyre();
}
}
说明:上面我们给处理高端汽车工厂和低端汽车工厂,当我们要使用时直接使用各自的工厂即可。
Client.java
package cn.itcast.day231.AbstractFactory;
//测试
public class Client {
public static void main(String[] args) {
CarFactory factory = new LuxuryCarFactory();
Engine engine = factory.createEngine();
engine.run();
engine.start();
}
}
说明:如上,如果我们需要一辆高端汽车,那么可以使用工厂直接生产我们需要的高端的引擎、座椅、轮胎。