创建者模式-抽象工厂模式
6.3抽象工厂模式⬆️⬆️⬆️
6.3.1概念
抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。在这种模式中,抽象工厂负责定义用于创建产品家族的方法,每个具体工厂类则负责实现这些方法以创建具体的产品。
6.3.2场景
我们正在开发一个电子商务网站,需要展示不同品牌的手机和其相关配件。我们可以使用抽象工厂模式来定义一个“手机及配件工厂”接口,然后针对每个品牌创建一个具体的工厂类,如苹果工厂、三星工厂等等。这些具体工厂类实现了“手机及配件工厂”接口,并实现了用于创建各自品牌手机及其相关配件的方法。最终,我们可以通过调用相应工厂类的方法来创建属于不同品牌的手机及其相关配件。
6.3.3优势 / 劣势
-
保证产品家族的一致性。抽象工厂模式可以确保创建出来的产品都是属于同一个产品家族,从而保证了产品之间的兼容性和稳定性。
-
客户端与具体产品解耦。通过使用抽象工厂模式,客户端只需要知道要使用哪个工厂对象即可,无需关心该工厂生产的具体产品对象是什么,从而减少了客户端与具体产品的耦合度。
-
符合开闭原则。抽象工厂模式在添加新产品时只需要增加相应的具体产品类和工厂类,无需修改已有代码,满足了开闭原则。
-
扩展产品族比较困难。当需要增加一个新的产品族时,除了需要添加新的具体产品类和工厂类外,还需要修改抽象工厂类的接口和所有具体工厂类的实现,因此扩展产品族比较困难。
-
增加了系统的抽象性和理解难度。由于抽象工厂模式对产品族进行了抽象和封装,因此在理解和设计系统时需要更高的抽象思维能力和设计能力,增加了系统的抽象性和理解难度。
6.3.4抽象工厂模式分为
- 抽象产品接口AbstractProduct:定义产品的接口,可以定义多个抽象产品接口,比如说沙发、椅子、茶几都是抽象产品
- 具体产品类ConcreteProduct:实现抽象产品接口,产品的具体实现,古典风格的沙发和现代风格的沙发都是具体产品
- 抽象工厂接口AbstractFactory:声明一组用于创建产品的方法,每个方法对应一个产品
- 具体工厂类ConcreteFactory:实现抽象工厂接口,负责创建一组具体产品的对象,在本例中,生产古典风格的工厂和生产现代风格的工厂都是具体实例
基本实现步骤
- 定义抽象产品接口(可以有多个),接口中声明产品的公共方法
- 实现具体产品类,在类中实现抽象产品接口中的方法
- 定义抽象工厂接口,声明一组用于创建产品的方法
- 实现具体工厂类,分别实现抽象工厂接口中的方法,每个方法负责创建一组相关的产品
- 在客户端中使用抽象工厂和抽象产品,而不直接使用具体产品的类名
6.3.5抽象工厂模式
package com.designpattern.mode.abstractfactory;
public class AbstractFactorys {
public static void main(String[] args) {
// 使用工厂1创建产品A1和产品B1
ConcreteFactory1 factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.display();
productB1.show();
// 使用工厂2创建产品A2和产品B2
ConcreteFactory2 factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.display();
productB2.show();
}
}
//1.定义抽象产品
//抽象产品A
interface ProductA{
void display();
}
//抽象产品B
interface ProductB{
void show();
}
//2.实现具体产品类
//具体产品A1
class ConcreteProductA1 implements ProductA{
@Override
public void display() {
System.out.println("Concrete Product A1");
}
}
//具体产品A2
class ConcreteProductA2 implements ProductA{
@Override
public void display() {
System.out.println("Concrete Product A2");
}
}
//具体产品B1
class ConcreteProductB1 implements ProductB{
@Override
public void show() {
System.out.println("Concrete Product B1");
}
}
//具体产品B2
class ConcreteProductB2 implements ProductB{
@Override
public void show() {
System.out.println("Concrete Product B2");
}
}
//3.定义抽象工厂接口
interface AbstractFactory{
ProductA createProductA();
ProductB createProductB();
}
//4.实现具体工厂类
//具体工厂1,生产产品A1和B1
class ConcreteFactory1 implements AbstractFactory{
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
//具体工厂2,生产产品A2和B2
class ConcreteFactory2 implements AbstractFactory{
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
6.3.6实战
6.3.6.1题目描述
小明家新开了两个工厂用来生产家具,一个生产现代风格的沙发和椅子,一个生产古典风格的沙发和椅子,现在工厂收到了一笔订单,请你帮他设计一个系统,描述订单需要生产家具的信息。
6.3.6.2输入描述
输入的第一行是一个整数 N(1 ≤ N ≤ 100),表示订单的数量。
接下来的 N 行,每行输入一个字符串,字符串表示家具的类型。家具类型分为 “modern” 和 “classical” 两种。
6.3.6.3输出描述
对于每笔订单,输出字符串表示该订单需要生产家具的信息。
modern订单会输出下面两行字符串
modern chair
modern sofa
classical订单会输出下面两行字符串
classical chair
classical soft
6.3.6.4代码
package com.designpattern.mode.abstractfactory;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//读取订单数量
int nums = scanner.nextInt();
//处理每个订单
for(int i=0;i<nums;i++){
//读取家具类型
String furnitureType = scanner.next();
//创建相应风格的家居装饰品工厂
FurnitureFactory factory=null;
if(furnitureType.equals("modern")){
factory = new ModernFurnitureFactory();
}else if(furnitureType.equals("classical")){
factory = new ClassicalFurnitureFactory();
}
//根据工厂生产椅子和沙发
Chair chair = factory.createChair();
Sofa sofa = factory.createSofa();
//输出家具信息
chair.showInfo();
sofa.displayInfo();
}
}
}
//抽象椅子接口
interface Chair{
void showInfo();
}
//具体实现椅子接口
//现代化风格椅子
class ModernChair implements Chair{
@Override
public void showInfo() {
System.out.println("modern chair");
}
}
//古典风格椅子
class ClassicalChair implements Chair{
@Override
public void showInfo() {
System.out.println("classical chair");
}
}
//抽象沙发接口
interface Sofa{
void displayInfo();
}
//具体实现沙发接口
//现代化风格沙发
class ModernSofa implements Sofa{
@Override
public void displayInfo() {
System.out.println("modern sofa");
}
}
//古典风格沙发
class ClassicalSofa implements Sofa{
@Override
public void displayInfo() {
System.out.println("classical sofa");
}
}
//抽象家居工厂接口
interface FurnitureFactory{
Chair createChair();
Sofa createSofa();
}
//具体现代风格家居工厂
class ModernFurnitureFactory implements FurnitureFactory{
@Override
public Chair createChair() {
return new ModernChair();
}
@Override
public Sofa createSofa() {
return new ModernSofa();
}
}
//具体古典风格家居工厂
class ClassicalFurnitureFactory implements FurnitureFactory{
@Override
public Chair createChair() {
return new ClassicalChair();
}
@Override
public Sofa createSofa() {
return new ClassicalSofa();
}
}
6.3.7简单工厂、方法工厂、抽象工厂的区别
- 简单工厂模式:一个工厂方法创建所有具体产品
- 方法工厂模式:一个工厂方法创建一个具体产品
- 抽象工厂模式:一个工厂方法创建一类具体产品
6.3.8总结
优点:由于简单工厂模式只依赖于产品的接口,添加新产品时就只需要增加相应的实现类和工厂类
总结:根据参数的不同返回不同类的实例
场景:适用于单一类产品的情况