设计模式之抽象工厂模式

序言

工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重问题,由于工厂模式中的每个工厂只能生产一类产品,可能会导致大量的工厂类,,势必会增加系统的开销,此时可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来生产。———这也就是抽象工厂的基本思想。

产品等级结构与产品族

在讲抽象工厂模式之前,我们必须明白两个概念: 产品等级结构 、 产品族。

  • 产品等级结构: 产品等级结构即产品的继承结构, 如一个抽象类是手游,其子类有腾讯的手游、 网易的手游、 盛大的手游等等。则抽象手游与具体游戏公司的手游构成一个产品等级结构,手游是父类,而其它具体公司的手游则是子类。
  • 产品族: 在抽象工厂模式中,产品族是指由同一个工厂生产,位于不同产品等级结构中的一组产品。如腾讯公司生产的手游、端游、页游, 腾讯的手游则位于手游产品等级结构中,腾讯的端游则位于端游产品结构中, 腾讯的手游、 端游、 页游就构成了一个产品族。
    设计模式之抽象工厂模式_第1张图片

我们看到不同的颜色的多个椭圆形、正方形、三角形分别构成了三个不同的产品等级结构,而颜色相同的椭圆、正方形、三角形构成一个产品族,可以看到每一个形状都位于某个产品族,并不属于某个产品等级结构,图中有4个产品族,分属于3个不同的产品等级结构。只要知道一个产品的所处的产品族和产品等级结构,就可以确定这个产品。

抽象工厂模式

定义:提供一个创建一系列相关或相互依赖的接口,而无需指定它们具体的类。抽象工厂模式又称为Kit模式,它也是一种对象创建型模式
设计模式之抽象工厂模式_第2张图片

在抽象工厂模式有一下几个角色:

  • AbstractProduct(抽象产品):为每种产品声明接口,在抽象产品中声明了产品所有的业务接口。
  • ConcrteProduct(具体产品) : 定义具体的工厂生产的具体产品对象,实现了抽象产品的所有方法。
  • AbstractFactory(抽象工厂):声明了创建一组用于创建一族产品的接口,每个方法对应一种产品。
  • ConcreteFactory(具体工厂):实现了抽象工厂中所有的接口,这些接口返回的产品构成了一个产品族,每个产品都位于某个产品等级结构中。

代码实现:

AbstractProduct(抽象产品)

   /**
 * @program
 * @Desc    抽象 产品A
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--18:56
 */
public abstract class AbstractProductA {
}
 /**
 * @program
 * @Desc    抽象 产品B
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--18:57
 */
public abstract class AbstractProductB {
}

ConcreteProduct(具体产品) : 产品A和产品B构成产品族, A1和A2构成产品等级结构。

    /**
 * @program
 * @Desc   具体的产品 A1
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--19:04
 */
public class ConcreteProductA1 extends AbstractProductA{
}
  /**
 * @program
 * @Desc   具体的产品 B1
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--19:04
 */
public class ConcreteProductB1 extends AbstractProductB{
}
 /**
 * @program
 * @Desc   具体的产品 A2
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--19:03
 */
public class ConcreteProductA2 extends AbstractProductA{
}
/**
 * @program
 * @Desc   具体的产品 B2
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--19:07
 */
public class ConcreteProductB2 extends AbstractProductB {
}

AbstractFactory(抽象工厂)

/**
 * @program
 * @Desc  抽象工厂
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--19:16
 */
public abstract class AbstractFactory {
    public abstract AbstractProductA createProductA();
    public abstract AbstractProductB createProductB();
}

ConcreteFactory(具体工厂)

/**
 * @program
 * @Desc  具体工厂 1
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--19:20
 */
public class ConcreteFactory1 extends AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }
    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB1();
    }
}
/**
 * @program
 * @Desc  具体工厂 2
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--19:21
 */
public class ConcreteFactory2 extends AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB2();
    }
}

客户端测试:

/**
 * @program
 * @Desc
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--19:25
 */
public class Test {
    public static void main(String args[]){
        //声明一个工厂1  就可以生产 A1和B1
     AbstractFactory factory1= new ConcreteFactory1();
     AbstractProductA productA1=factory1.createProductA();
     AbstractProductB productB1=factory1.createProductB();

        //声明一个工厂2  就可以生产 A2和B2
     AbstractFactory factory2= new ConcreteFactory2();
     AbstractProductA productA2=factory2.createProductA();
     AbstractProductB productB2=factory2.createProductB();
        
    }
}

“开闭原则”的倾斜性

在抽象工厂模式中,增加新的产品族很方便,但是增加新的产品等级结构就很麻烦,抽象工厂模式的这种性质称为**“开闭原则“的倾斜性**

  • 增加产品族: 对于增加新的产品族,只需要增加个具体的产品并对应增加个具体工厂,对已有的代码不用修改,符合”开闭原则“。
  • 增加新的产品等级结构: 对于增加新的产品等级结构,就需要修改工厂角色,包括抽象工厂,需要增加新产品的方法,相应的具体工厂也要改。 违背了”开闭原则“

”增加产品族“ 代码如下:

新增的产品族:

/**
 * @program
 * @Desc
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--20:33
 */
public class ConcreteProductA3 extends AbstractProductA {
}
/**
 * @program
 * @Desc
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--20:33
 */
public class ConcreteProductB3 extends AbstractProductB {
}

新增具体的工厂类

/**
 * @program
 * @Desc
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--20:34
 */
public class ConcreteFactory3 extends AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA3();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB3();
    }
}

客户端测试:

 /**
 * @program
 * @Desc
 * @Author 游戏人日常
 * @CreateTime 2019/07/15--19:25
 */
public class Test {
    public static void main(String args[]){
        //声明一个工厂1  就可以生产 A1和B1
     AbstractFactory factory1= new ConcreteFactory1();
     AbstractProductA productA1=factory1.createProductA();
     AbstractProductB productB1=factory1.createProductB();

        //声明一个工厂1  就可以生产 A2和B2
     AbstractFactory factory2= new ConcreteFactory2();
     AbstractProductA productA2=factory2.createProductA();
     AbstractProductB productB2=factory2.createProductB();

        //(新增)  声明一个工厂3  就可以生产 A3和B3
      AbstractFactory factory3= new ConcreteFactory3();
      AbstractProductA productA3=factory2.createProductA();
      AbstractProductB productB3=factory2.createProductB();

    }
}

总结

抽象工厂模式是工厂方法模式的进一步延申,继承了工厂方法模式的优点,也弥补了工厂方法模式的一些缺点。 工厂方法模式针对的是一个产品等级结构,而抽象工厂模式是面对多个产品等级结构。

抽象工厂模式增加产品族方便,无需修改代码,只需增加具体的产品类和具体工厂类,符合”开闭原则“。 增加产品等级结构就需要改工厂类(抽象和具体的工厂都改)

抽象模式优缺点

优点

  • 抽象工厂模式隔离了具体类的生成,使得客户端并不需要知道什么被创建,由于这种隔离,更换一个具体工厂相对容易些。
  • 当一个产品族中的多个对象被设计成一起工作时,这样能够保证客户端始终只使用同一个产品族中的对象。
  • 增加新的产品族很方便,无需修改已有代码,符合“开闭原则”。

缺点

  • 增加新的产品等级结构麻烦,需要对原来的系统有较大的修改,还会修改抽象层代码,这不符合”开闭原则“

适用场景

  • 一个系统不应当依赖于产品实例如何被创建、组合和表达的细节,这对于所有的工厂模式都是很重要,用户无需关系对象的创建过程,将对象的创建与使用解耦。
  • 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来,同一产品族的产品可以是没有任何关系,但是它们都具有一些共同的约束
  • 产品等级结构稳定,设计完成后,不会向系统中增加新的产品等级结构。
    一个游戏技术人,分享Java、Python、H5、Android 等知识。同时会分享游戏行业日常。

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