开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 11 天,点击查看活动详情
觉得对你有益的小伙伴记得点个赞+关注
后续完整内容持续更新中
希望一起交流的欢迎发邮件至javalyhn@163.com
1. 工厂模式定义
提供了一种创建对象的最佳方式。我们不必关心对象的创建细节,只需要根据不同情况获取不同产品即可。
工厂模式分为三种:
- 简单工厂(Simple Factory)静态工厂
- 工厂方法(Factorty Method)多态工厂
- 抽象工厂(Abstract Factory)
2. 工厂模式使用场景
- NumberFormat、SimpleDateFormat
- LoggerFactory:
- SqlSessionFactory:MyBatis
- BeanFactory:Spring的BeanFactory(就是为了造出bean)
3. 简单工厂的实现
我们假设有下面一个造车的场景
有三个角色:
- Factory:工厂角色, WuLinFactory
- Product:抽象产品角色,Car
- ConcreteProduct:具体产品角色, VanCar、MiniCar
Car
/**
* 工厂的产品
*/
public abstract class AbstractCar {
String engine;
public abstract void run();
}
VanCar
/**
* 具体产品
*/
public class VanCar extends AbstractCar{
public VanCar(){
this.engine = "单杠柴油机";
}
@Override
public void run() {
System.out.println(engine+"--》嗒嗒嗒....");
}
}
MiniCar
public class MiniCar extends AbstractCar{
public MiniCar(){
this.engine = "四缸水平对置发动机";
}
@Override
public void run() {
System.out.println(engine+"--> 嘟嘟嘟...");
}
}
WuLinSimpleFactory
/**
* 简单工厂
* 1、产品数量极少
*/
public class WuLinSimpleFactory {
/**
*
* @param type Class: 好像具有扩展性,但是没有解决实际问题
* @return
*/
public AbstractCar newCar(String type){
//核心方法:一切从简
if("van".equals(type)){
// 钣金、喷漆、放发动机、申请环保
return new VanCar();
}else if("mini".equals(type)){
return new MiniCar();
}
//.....
//更多的产品,违反开闭原则。应该直接扩展出一个类来造
return null;
}
}
MainTest
public class MainTest {
public static void main(String[] args) {
WuLinSimpleFactory factory = new WuLinSimpleFactory();
AbstractCar van = factory.newCar("van");
AbstractCar mini = factory.newCar("mini");
AbstractCar zz = factory.newCar("zz");
van.run();
mini.run();
}
}
这个简单工厂方法相信大家一看就知道弊端:if...else... 不符合开闭原则,而且仅适用于类数量少的情况。
4. 工厂方法的实现
这次同样使用造车的场景,但是有区别
这次有四个角色
- Product:抽象产品
- ConcreteProduct:具体产品
- Factory:抽象工厂
- ConcreteFactory:具体工厂
AbstractCar
/**
* 工厂的产品
*
* 怎么把一个功能提升一个层次:定义抽象(抽象类,接口)
* 抽象类,接口 就会有多实现,多实现自然就有多功能
*/
public abstract class AbstractCar {
String engine;
public abstract void run();
}
VanCar
/**
* 具体产品
*/
public class VanCar extends AbstractCar{
public VanCar(){
this.engine = "单杠柴油机";
}
@Override
public void run() {
System.out.println(engine+"--》嗒嗒嗒....");
}
}
RacingCar
public class RacingCar extends AbstractCar{
public RacingCar(){
this.engine = "v8发动机";
}
@Override
public void run() {
System.out.println(engine+"=--嗖.....");
}
}
MiniCar
public class MiniCar extends AbstractCar{
public MiniCar(){
this.engine = "四缸水平对置发动机";
}
@Override
public void run() {
System.out.println(engine+"--> 嘟嘟嘟...");
}
}
AbstractCarFactory
/**
* 抽象工厂的层级
*/
public abstract class AbstractCarFactory {
public abstract AbstractCar newCar();
//我能造口罩.....
}
WulinMinCarFactory
/**
* minicar分厂
*/
public class WulinMinCarFactory extends AbstractCarFactory{
@Override
public AbstractCar newCar() {
return new MiniCar();
}
}
WulinRacingCarFactory
/**
* RacingCar分厂
*/
public class WulinRacingCarFactory extends AbstractCarFactory{
@Override
public AbstractCar newCar() {
return new RacingCar();
}
}
WulinVanCarFactory
public class WulinVanCarFactory extends AbstractCarFactory {
@Override
public AbstractCar newCar() {
return new VanCar();
}
}
MainTest
public class MainTest {
public static void main(String[] args) {
AbstractCarFactory carFactory = new WulinRacingCarFactory();
AbstractCar abstractCar = carFactory.newCar();
abstractCar.run();
carFactory = new WulinVanCarFactory();
AbstractCar abstractCar1 = carFactory.newCar();
abstractCar1.run();
}
}
可见,我们省去了ifelse判断,使用了多态方式来建造对象,因此也有十分多的类。
缺点是:缺点:系统复杂度增加,产品单一
5. 抽象工厂的实现
抽象工厂模式:
为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
每一个工厂都有它的产品族,每个产品族都有对应的产品,实现了想要什么就造什么的情景。
WulinFactory
/**
* 总厂规范:
* Wulin集团
*
* 使用接口;
*/
public abstract class WulinFactory {
List<String> rules;
abstract AbstractCar newCar();
abstract AbstractMask newMask();
}
WulinCarFactory
/**
* wulin 汽车集团
*/
public abstract class WulinCarFactory extends WulinFactory{
@Override
abstract AbstractCar newCar();
@Override
AbstractMask newMask() {
return null;
}
}
WulinVanCarFactory
/**
* 分厂:VanCar
*/
public class WulinVanCarFactory extends WulinCarFactory{
@Override
AbstractCar newCar() {
return new VanCar();
}
}
WulinRacingCarFactory
/**
* 具体工厂。只造车
*/
public class WulinRacingCarFactory extends WulinCarFactory {
@Override
AbstractCar newCar() {
return new RacingCar();
}
}
AbstractCar
/**
* 工厂的产品
*
* 怎么把一个功能提升一个层次:定义抽象(抽象类,接口)
* 抽象类,接口 就会有多实现,多实现自然就有多功能
*/
public abstract class AbstractCar {
String engine;
public abstract void run();
}
VanCar
/**
* 具体产品
*/
public class VanCar extends AbstractCar {
public VanCar(){
this.engine = "单杠柴油机";
}
@Override
public void run() {
System.out.println(engine+"--》嗒嗒嗒....");
}
}
RacingCar
public class RacingCar extends AbstractCar {
public RacingCar(){
this.engine = "v8发动机";
}
@Override
public void run() {
System.out.println(engine+"=--嗖.....");
}
}
以上是汽车工厂,下面是口罩工厂
WulinHangZhouMaskFactory
/**
* 只造口罩
*/
public class WulinHangZhouMaskFactory extends WulinMaskFactory {
@Override
AbstractMask newMask() {
return new CommonMask();
}
}
WulinMaskFactory
/**
* wulin口罩集团
*/
public abstract class WulinMaskFactory extends WulinFactory{
@Override
AbstractCar newCar() {
return null;
}
abstract AbstractMask newMask();
}
WulinHangZhouMaskFactory
/**
* 只造口罩
*/
public class WulinHangZhouMaskFactory extends WulinMaskFactory {
@Override
AbstractMask newMask() {
return new CommonMask();
}
}
WulinWuHanMaskFactory
/**
* 分厂:口罩
*/
public class WulinWuHanMaskFactory extends WulinMaskFactory{
@Override
AbstractMask newMask() {
return new N95Mask();
}
}
AbstractMask
/**
* 抽象产品
*/
public abstract class AbstractMask {
Integer price;
public abstract void protectedMe();
}
CommonMask
public class CommonMask extends AbstractMask{
public CommonMask(){
price = 1;
}
@Override
public void protectedMe() {
System.out.println("普通口罩....简单保护...请及时更换");
}
}
N95Mask
/**
* 具体产品
*/
public class N95Mask extends AbstractMask{
public N95Mask(){
this.price = 2;
}
@Override
public void protectedMe() {
System.out.println("N95口罩....超级防护");
}
}
MainTest
/**
* 抽象出来。
* 可以抽象成接口(只有方法),可以抽象成抽象类(有些属性也需要用)
*/
public class MainTest {
public static void main(String[] args) {
WulinFactory wulinFactory = new WulinWuHanMaskFactory();
AbstractMask abstractMask = wulinFactory.newMask();
abstractMask.protectedMe();
wulinFactory = new WulinHangZhouMaskFactory();
AbstractMask abstractMask1 = wulinFactory.newMask();
abstractMask1.protectedMe();
wulinFactory = new WulinRacingCarFactory();
wulinFactory.newCar().run();
}
}
6. 工厂模式的退化
当抽象工厂模式中每一个具体工厂类只创建一个产品对象
,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式
;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式
。
7. 工厂模式优点
良好的封装性,代码结构清晰:
用户想要一个具体的产品对象,只需要知道这个产品的类名(约束字符串)即可,关于如何创建这个类,是不需要知道的,降低了模块间的耦合。工厂方法模式的拓展性十分优秀:
只需要适当的修改一个工厂类或者拓展一个工厂类即可完成。屏蔽产品类:
这个特点很重要,用户只需关心产品的接口,只要接口保持不变,系统的上层模块就不会发生变化。
举一个工厂方法的例子
如果使用JDBC连接数据库,数据库从MySQL切换到Oracle,需要改动的地方就是切换一下驱动名称(前提是SQL是标准语句),其他的都不要修改,这是工厂模式灵活的一个案例。
最后,工厂方法模式是典型的解耦框架,高层模块需要知道产品的抽象类,其他的实现类都不用担心,符合迪米特法则,我不需要的就不去交流,也符合依赖倒置原则,只依赖产品类的抽象;当然也符合里氏替换原则,使用产品子类替换产品父类,没问题。
8. 抽象工厂模式优缺点
8.1 抽象工厂模式优点
封装性:
每个产品的实现类不是高层模块要关心的,关心的是接口,是抽象类。只要知道工厂类是谁,我们就能创造出需要的对象,省时省力
产品族内的约束为非公开状态
。
8.2 抽象工厂模式缺点
产品族拓展十分困难。因为我们要增加一个产品类C,既向产品族中多填一个工厂来创建C,因此又要天将很多的类。
再说说往一个已经实现的工厂类中添加一个方法,接着它的实现类都要去增加,严重违反了开闭原则
。