java设计模式之抽象工厂模式

定义:

抽象工厂模式指提供一个创建一系列相关或者相互依赖对象的接口,无须指定他们具体的类,意思是客户端不必指定产品的具体类型,创建多个产品族中的产品对象。

抽象工厂模式中,客户端不依赖产品类如何被创建,实现等细节,强调一系列相关的产品对象一起创建对象,需要大量重复的代码

需要提供一个产品的类库,所有的产品以同样的接口出现,从而使客户端不依赖具体的实现

产品等级结构和产品族

java设计模式之抽象工厂模式_第1张图片

上图中有矩形,圆形和菱形3中图形,相同颜色,相同深浅的代表同一个产品族,相同形状的代表同一个产品等级。

应用场景:

抽象工厂模式适用于需要生成产品族的情景,抽象产品类内部提供了多个其他抽象产品,抽象工厂类定义了产品的创建接口,通过具体的工厂子类,就可以生产相应的产品族对象,供用户端使用

抽象工厂的UML类图:

 java设计模式之抽象工厂模式_第2张图片

 

右上图可知,抽象工厂模式主要包含4个角色

  1. 抽象工厂:声明创建抽象产品对象的一个操作接口

  2. 具体工厂:实现创建具体产品对象的操作

  3. 抽象产品:为一类产品对象声明一个接口

  4. 具体产品:定义一个将被相应的具体工厂创建的产品对象,实现AbstractProduct接口

抽象工厂模式的通用写法:

public class Client{
  public static void main(String[] args){
    IFactory factory = new ConcreateFactoryA();
    factory.makeProductA();
    factory.makeProductB();
    
    factory = new ConcreateFactoryB();
    factory.makeProductA();
    factory.makeProductB();
  }
}
//抽象工厂
public interface IFactory{
  IProductA makeProductA();
  
  IProductB makeProductB();
}
//产品A抽象
public interface IProductA{
  void doA();
}
//产品B抽象
public interface IProductB{
  void doB();
}
//产品族A的具体产品A
public class ConcreateProductAWithFamilyA implements IProductA{
  public void doA(){
    System.out.println("The ProductA be part of FamilyA")
  }
}
//产品族A的具体产品B
public class ConcreateProductWBithFamilyA implements IProductB{
  public void doB(){
    System.out.println("The ProductB be part of FamilyA")
  }
}
//产品族B的具体产品A
public class ConcreateProductAWithFamilyB implements IProductA{
  public void doA(){
    System.out.println("The ProductA be part of FamilyB")
  }
}
//产品族B的具体产品B
public class ConcreateProductWBithFamilyB implements IProductB{
  public void doB(){
    System.out.println("The ProductB be part of FamilyB")
  }
}
//具体工厂类A
public class ConcreateFactoryA implements IFactory{
  public IProductA makeProductA(){
    return new ConcreateProductAWithFamilyA();
  }
  
  public IProductB makeProductB(){
    return new ConcreateProductBWithFamilyA();
  }
}

//具体工厂类B
public class ConcreateFactoryB implements IFactory{
  public IProductA makeProductA(){
    return new ConcreateProductAWithFamilyB();
  }
  
  public IProductB makeProductB(){
    return new ConcreateProductBWithFamilyB();
  }
}

实例:

我们来看一个具体的业务场景,并且用代码来实现。还是以课程为例,假设每个课程要提供课程的录播视频还有课堂笔记,相当于现在的业务包括一个课程要有课程信息,录播视频,课堂笔记,甚至提供源码,首先在产品等级中增加两个产品,录播视频和课堂笔记

IVideo接口的代码如下:

public interface IVideo{
  void record();
}

INote接口代码如下

public interface INote{
  void note();
}

然后创建一个抽象工厂CourseFactory类:

public abstract class CourseFactory{
  public void init(){
    System.out.println("初始化基础数据");
  }
  protected abstract INote createNote();
  protected abstract IVideo createVideo();
}

接下来创建Java产品族,Java视频JavaVideo类的代码如下:

public class JavaVideo implements IVideo{
  public void record(){
    System.out.println("录制Java视频");
  }
}

扩展产品等级Java课堂笔记JavaNote类

public class JavaNote implements INote{
  public void note(){
    System.out.println("编写Java笔记");
  }
}

创建java产品族的具体工厂JavaCourseFactory

public class JavaCourseFactory extends CourseFactory{
  public INote createNote(){
    super.init();
    return new JavaNote();
  }
  public IVideo createVideo(){
    super.init();
    return new JavaVideo();
  }
}

随后创建Python产品族,Python视频PythonVideo类的代码如下

public class PythonVideo implements IVideo{
  public void record(){
    System.out.println("录制python视频");
  }
}

扩展产品等级Python课堂笔记PythonNote类

public class PythonNote implements INote{
  public void note(){
    System.out.println("编写Python笔记");
  }
}

创建Python产品族的具体工厂PythonCourseFactory

public class PythonCourseFactory extends CourseFactory{
  public INote createNote(){
    super.init();
    return new PythonNote();
  }
  public IVideo createVideo(){
    super.init();
    return new PythonVideo();
  }
}

最后来看客户端调用代码

public static void main(String[] args){
  JavaCourseFactory factory = new JavaCourseFactory();
  factory.createNote().note();
  factory.createVideo().record();
}

上面代码完整的描述了Java课程和Python课程两个产品族,抽象工厂模式非常清晰描述了这样一层的复杂关系。但是,不知道如果继续扩展产品,将Source也加入课程中,则代码从抽象工厂到具体的工厂要全部调整,这显然不符合开闭原则。

优点:

  1. 当需要产品族时,抽象工厂可以保证客户端始终只是用同一个产品的产品族

  2. 抽象工厂增强了程序的可扩展性,对于新产品族的增加,只需实现一个新的具体工厂即可,不需要对已有代码进行修改,符合开闭原则

缺点:

  1. 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口

  2. 增加了系统的抽象性和理解难度

你可能感兴趣的:(设计模式,抽象工厂模式)