前言
上文描述了简单工厂模式,但是简单工厂模式并不属于23种设计模式。所以本文我们介绍简单工厂模式的高级实现。在此之前先看一下简单工厂模式所存在的问题。预留问题:
- 违背了开闭原则还违反了高内聚低耦合的原则。
- 无法形成继承的层级结构
工厂方法模式
工厂方法模式(Factory Method Pattern)又称为工厂模式,又称工厂模式、多态工厂模式和虚拟构造器模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
主要作用
工厂方法模式主要把类的创建放到工厂的子类中进行创建,同时由子类来决定创建哪一个类
举个例子,上文中小明有一个自己的简单汽车工厂可以生产汽车,这时候甲方来了说能不能生产一批自行车?
这时候咋办 小明就只有去改造他的汽车简单工厂了,但是成本太高了。而且搞不好甲方又要生产其他的产品呢。所以这次必须要完美的解决这个问题。所以小明去请教了一个企业家。
企业家的建议就是创建生产自行车的工厂,不改造原有的汽车工厂,这样的话每次甲方有新的需求只需要创建一个工厂就行,这样也不用害怕甲方在增加其他的产品。这就是工厂方法模式。
总结
上述就是简单工厂模式和工厂方法模式的区别,简单工厂模式产品单一,扩展难 这时候我们来看一下都有哪些角色。
- 抽象产品(Product)
- 具体产品(Concrete Product)
- 抽象工厂(Creator)
- 具体工厂(Concrete Creator) 简单示意图:
实例
还是拿上文中的汽车工厂举例子 首先创建抽象工厂类汽车工厂
public abstract class CarFactory {
public abstract Car getCar();
}
抽象产品角色,我们的产品就是生产汽车,注意汽车和自行车都是属于同一产品等级,产品等级和产品族的概念等下文介绍
public interface Car {
/**
* 输出简单信息
*/
void output();
}
然后创建具体产品,这里生产奥迪汽车和凤凰牌自行车
/**
* 奥迪汽车产品
*/
public class AudiCar implements Car {
@Override
public void output() {
System.out.println("生产出了奥迪车");
}
}
/**
* 凤凰牌自行车
*/
public class BicycleCar implements Car {
@Override
public void output() {
System.out.println("生产凤凰牌自行车");
}
}
然后创建具体工厂类,然后继承抽象工厂类。
/**
* 生产汽车
*/
public class AutomobileFactory extends CarFactory {
@Override
public Car getCar() {
return new AudiCar();
}
}
/**
* 生产自行车
*/
public class BicycleFactory extends CarFactory{
@Override
public Car getCar() {
return new BicycleCar();
}
}
然后我们创建一个客户端来进行调用。
public static void main(String[] args) {
/**
* 生产汽车
*/
CarFactory carFactory = new AutomobileFactory();
Car car = carFactory.getCar();
car.output();
/**
* 生产自行车
*/
CarFactory bicFactory = new BicycleFactory();
Car biccar = bicFactory.getCar();
biccar.output();
}
输出结果
如果这个时候要开始生产电动车了哪我们就可以直接创建一个电动车的产品工厂,然后继承抽象工厂,在创建具体的产品就可以了
缺点
会造成大量的类,在添加新产品的时候不光要增加产品类还要增加对应的工厂类。对系统造成了额外的开销,同时也增加了系统的负责度,还有就是一个具体工厂只能创建一个具体的产品。虽然说解决了对工厂方法内的修改关闭,如果换一个产品的话也是需要修改具体的产品类。
优点
- 符合开闭原则
- 符合单一职责原则
- 解决类简单工厂模式无法继承等级结构问题
其主要就是:将静态工厂里的工厂类用继承的方式细分
应用实例
接下来我们看一下在Java中有哪些使用工厂方法模式的例子 Collection接口
Collection接口可以看成一个总的抽象工厂,它的一些实现这个接口的类,像ArrayList,LinkedHashSet等等可以看作一个个不同的品牌的工厂,而总的产品Iterator接口里面会定义产品所需功能的细节,然后在交给各个品牌不同的工厂来实现。