定义与类型
定义:定义一个创建对象的接口,但让实现这个接口的类来决定实例化那个类,工厂方法让类的实例化推迟到子类中进行
类型:创建型
适用场景
- 创建对象需要大量重复的代码
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
- 一个类通过其子类来指定创建那个对象(利用面向对象的多态性和里氏替换原则,子类对象覆盖父类对象)
优点
- 用户只需要关心所需产品对应的工厂,无需关心创建细节
- 加入新产品符合开闭原则,提高可扩展性
缺点
- 类的个数容易过多,增加复杂度(添加新的产品,需要创建新的产品类,还要创建新的产品对应的工厂类)
- 增加了系统的抽象性和理解难度
Coding
package com.jpg.creational.factorymethod;
public abstract class Video {
/**
* 录制视频的抽象方法
*/
public abstract void produce();
}
~~-----------------------------~~
package com.jpg.creational.factorymethod;
public abstract class VideoFactory {
/*
* 和简单工厂不同的是,原先需要在VideoFactroy类中直接创建
* 需要的对象,工厂方法将这一层抽象了出来,让类的实例化推迟到子类中进行
*
* 关于使用Interface和抽象类
* 使用抽象类:在实际业务场景中,对于某些行为和属性是已知的
* 除了抽象方法还有已知的实现,用抽象类比较合理,如果全部是未知用接口就行了
*
* 工厂方法是为了解决同一产品等级的业务抽象问题,对于Java视频和Python视频是同一个产品等级
* 都属于Video这一个等级
*
* 这个类只定义规范,并不决定产生哪一种类型的视频,产生那一中类型的视频交由子类实现
*/
public abstract Video getVideo();
}
~~-----------------------------~~
package com.jpg.creational.factorymethod;
public class JavaVideoFactory extends VideoFactory {
@Override
public Video getVideo() {
return new JavaVideo();
}
}
~~-----------------------------~~
package com.jpg.creational.factorymethod;
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("录制Java课程视频");
}
}
~~-----------------------------~~
package com.jpg.creational.factorymethod;
public class Test {
/*
* 视频和笔记打包在一起称为教程
* Java的视频、Java的笔记都属于Java教程,属于同一产品族
* Java的视频、Python的视频、FE的视频都属于同一产品等级
* Java的笔记、Python的笔记、FE的笔记都属于同一产品等级
* 同一产品等级和同一产品族的概念的理解
* 抽象工厂主要解决同一产品族的问题
* 工厂方法和抽象工厂的区别就在于此
*/
public static void main(String[] args) {
VideoFactory videoFactory = new JavaVideoFactory();
Video video = videoFactory.getVideo();
video.produce();
}
}
JDK源码解析
Collection里面的Iterator方法
Collection相当于VideoFactory
ArrayList相当于具体的实现工厂例如JavaVideoFactory
Iterator相当于Video是一个抽象产品
ArrayList里面的Itr相当于JavaVideo是一个具体产品
URLStreamHandlerFactory对应的是VideoFactory
URLStreamHadler对应Video抽象产品
URLStreamHadler这个抽象类的实现是具体的产品