3.工厂模式
按照业务场景划分:一、简单工厂模式,二、工厂方法模式,三、抽象工厂模式。
3.1 简单工厂模式
即静态工厂方法模式,有一个具体工厂,创建多个不同的产品。
3.1.1 应用场景
对于产品种类较少的。
3.2 工程方法模式
- 多态性工程模式,指创建一个对象的接口,但由实现这个接口的类来定义实例化哪个类,工厂方法把类的实例化推迟到子类种进行。
- 在工厂模式种,不在由单一的工厂里生产产品,而是由工厂类的子类实现具体产品的创建,因此,增加一个产品时,只需增加一个对应的工厂的子类。
3.2.1 工厂方法模式应用场景
- 创建对象需要大量的重复代码。
- 客户端(应用层)不依赖产品类实例如何被创建、实现等细节。
- 一个类通过其子类来指定创建哪个对象。
3.2.2 UML图

- 抽象工厂模式主要包含四个角色;
- 抽象工厂(IFactory):是工厂模式的核心,与应用程序无关。任何模式种创建的对象的工厂斗必须实现这个接口。
- 具体工厂(FactoryA、B):实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且被应用程序调用以创建具体产品对象。
- 具体产品(ProductA、B):这个角色实现了抽象产品角色定义的接口。某具体产品由具体工厂创建。两者一一对应。
3.2.3 通用写法
public class Client {
public static void main(String[] args) {
IFactory factory = new FactoryA();
factory.makeProduct().doSomething();
factory = new FactoryB();
factory.makeProduct().doSomething();
}
//抽象工厂
public interface IFactory{
IProduct makeProduct();
}
//生产产品A的具体工厂类
static class FactoryA implements IFactory{
public IProduct makeProduct() {
return new ProductA();
}
}
//生产产品B的具体工厂类
static class FactoryB implements IFactory{
public IProduct makeProduct() {
return new ProductB();
}
}
//抽象产品
public interface IProduct{
void doSomething();
}
//产品A
static class ProductA implements IProduct{
public void doSomething() {
System.out.println("Product A");
}
}
//产品B
static class ProductB implements IProduct{
public void doSomething() {
System.out.println("Product B");
}
}
}
- 结果

3.2.4 使用工厂方法模式实现产品扩展
- 工厂模式主要解决产品扩展的问题,在简单工厂种,如果每个产品的创建逻辑有区别,则导致工厂的职责会变多,因此根据单一原则,专人干专事。例如一个课程由一个老师来教,一个产品由一个工厂生产。
- 抽象工厂
public interface IcourseFactory {
ICourse create();
}
- 具体工厂
public class ChineseCourseFactory implements IcourseFactory {
public ICourse create() {
return new ChineseCourse();
}
}
public class MathCourseFactory implements IcourseFactory {
public ICourse create() {
return new MathCourse();
}
}
- 抽象产品
public interface ICourse {
void course();
}
- 具体产品
public class ChineseCourse implements ICourse {
public void course() {
System.out.println("这是语文课程生产");
}
}
public class MathCourse implements ICourse {
public void course() {
System.out.println("这是数学课生产");
}
}
3.2.5 工厂模式优缺点
- 优点:
- 灵活性增强,对于新产品的创建,只需要多谢一个工厂类。
- 典型的解耦框架,高层模块只需要知道产品的抽象类,无需关心其他实现类。
- 缺点:
- 类的个数容易过多,增加复杂度。
- 增加了系统的抽象性和理解程度。
- 抽象产品只能生产一种产品。
3.3 抽象工厂模式
- 抽象工厂模式指提供一个创建一系列相关或相互依赖对象的接口,无需指定他们具体的类,意思是客户端不必指定产品的具体类型,创建多个产品族种的产品对象。
- 在抽象工厂模式中,客户端(应用层)不依赖产品实例如何被创建,实现等细节,强调一系列相关的产品对象(属于同一产品族)一起创建对象,需要大量重复的代码。
- 需要提供一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖具体实现。
3.3.1 产品等级结构和产品族

- 相同颜色代表同一个产品族,相同形状代表产品等级结构。
- 另一个理解就是同一个产品族就是同一个品牌,即小米,海尔,格力,而同一个品牌下面则有不同的产品即产品等级结构,比如冰箱,手机,空掉。
3.3.2 抽象工厂模式的应用场景
- 抽象工厂模式适用于需要生产产品族的情景,抽象产品内部提供多个其他抽象产品,抽象工厂类定义了产品的创建接口,通过具体的工厂子类,就可以生产相对应的产品族对象,供客户端使用。
3.3.3 抽象工厂模式UML图

- 抽象工厂主要包含4个角色
- 抽象工厂:声明创建抽象产品对象的一个操作接口。
- 具体工厂:实现创建具体产品对象的操作。
- 抽象产品:位一类产品对象声明一个接口。
- 具体产品:定义一个将被相应的具体工程创建的产品对象,AbstractProduct接口。
3.3.4 抽象工厂模式的通用写法
public class Client {
public static void main(String[] args) {
IFactory factory = new ConcreteFactoryA();
factory.makeProductA().doA();
factory.makeProductB().doB();
factory = new concreteFactoryB();
factory.makeProductA().doA();
factory.makeProductB().doB();
}
//抽象工厂
public interface IFactory{
IproductA makeProductA();
IproductB makeProductB();
}
//产品A抽象
public interface IproductA{
void doA();
}
//产品B抽象
public interface IproductB{
void doB();
}
//产品族A的具体产品A
static class ConcreteProductAWithFamilyA implements IproductA{
public void doA() {
System.out.println("ProductA belong FamilyA");
}
}
//产品族A的具体产品B
static class ConcreteProductBWithFamilyA implements IproductB{
public void doB() {
System.out.println("ProductB belong FamilyA");
}
}
//产品族B的具体产品A
static class ConcreteProductAWithFamilyB implements IproductA{
public void doA() {
System.out.println("ProductA belong FamilyB");
}
}
//产品族B的具体产品B
static class ConcreteProductBWithFamilyB implements IproductB{
public void doB() {
System.out.println("ProductB belong FamilyB");
}
}
//具体工厂A
static class ConcreteFactoryA implements IFactory{
public IproductA makeProductA() {
return new ConcreteProductAWithFamilyA();
}
public IproductB makeProductB() {
return new ConcreteProductBWithFamilyA();
}
}
//具体工厂B
static class concreteFactoryB implements IFactory{
public IproductA makeProductA() {
return new ConcreteProductAWithFamilyB();
}
public IproductB makeProductB() {
return new ConcreteProductBWithFamilyB();
}
}
}
3.3.5 使用抽象工厂模式支持产品扩展
- 业务场景:每个课程开始,不仅要提供书本,还有PPT,以及课堂笔记。
- 产品等级IPPT:
public interface IPPT {
void download();
}
- 产品等级Note
public interface INote {
void edit();
}
- 抽象工厂CourseFacotry类
/**
* 抽象工厂是用户的主入口,
* 在Spring框架中使用最广泛。
* 易于扩展
*/
public abstract class CourseFactory {
public void init(){
System.out.println("初始化基础数据");
}
protected abstract INote createNote();
protected abstract IPPT createDownload();
}
- 语文产品族
public class ChineseNote implements INote{
public void edit() {
System.out.println("编写语文笔记");
}
}
public class ChinesePPT implements IPPT{
public void download() {
System.out.println("编写语文PPT");
}
}
- 语文产品的具体工厂ChineseCourseFacotry
public class ChineseCourseFactory extends CourseFactory{
protected INote createNote() {
super.init();
return new ChineseNote();
}
protected IPPT createDownload() {
super.init();
return new ChinesePPT();
}
}
- 数学产品族同理
- 测试代码
public class AbstractfactoryTest {
@Test
public void test1(){
ChineseCourseFactory factory = new ChineseCourseFactory();
factory.createDownload().download();
factory.createNote().edit();
}
}
- 结果

3.3.6 抽象工厂模式重构数据库连接池
- 使用抽象工厂模式,将数据库预先创建好,放到容器种缓存,当业务调用时就只需取用。
- //TODO
3.3.7 抽象工厂在Spring源码中应用
-
在Spring中,所有工厂斗士BeanFactory的子类,通过对BeanFacotry的实现,我们可以从Spring的容器访问Bean。根据不同的策略调用getBean()方法,从而获具体对象。
-
Spring源码解析一章。//TODO
3.3.8 抽象工厂模式的优缺点
- 优点
- 当需要产品族时,抽象工厂可以保证客户端始终指使用同一个产品的产品族。
- 抽象工厂增强了程序的可扩展性,对于新产品族的增加,只需要实现一个新的具体工厂,不需要对已有代码进行修改。
- 缺点:
- 规定了所有可能被创建的产品集合,产品族汇总扩展信的产品困难,需要修改抽象工厂的接口。
- 增加了系统的抽象性和理解难度。
网友评论