专栏首页海向抽象工厂模式

抽象工厂模式

?原文地址为https://www.cnblogs.com/haixiang/p/12055272.html,转载请注明出处!

简介

工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、计算机软件学院只培养计算机软件专业的学生等。

同种类称为同等级,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。

本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

优缺点

  • 产品易扩展(例如后面案例中扩展新的Mq、数据库、缓存)
  • 产品族扩展非常困难(例如后面案例中新增Server产品族),要增加一个系列的某一产品,既要在抽象工厂里加代码,又要在具体的工厂类里面加代码。

使用场景

  1. 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  2. 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
  3. 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

具体案例

一个完整成熟的系统可以采用不同的技术来解决业务层面的问题,例如数据库可以用Mysql也可以用Oracle。本例中提供了三个产品,分别是消息队列Mq、数据库DataBase以及缓存Mycache三个接口,每个接口下都有自己的具体实现类,也就是工厂的产品。AbstractSystemFac作为抽象工厂类,调用了上述的三个接口,来组装三个不同的产品。SimpleSystemFacHugeSystemFac是两个具体的工厂类,SimpleSystemFac是一个技术解决方案,选用MySQL数据库、MemCache、RabbitMQ三种产品来实现自己的技术架构。而HugeSystemFac采用Oracle数据库、Redis、Kafka三种产品,这两个工厂类的方法一致,只不过具体调用的产品类型不同。

数据库接口及实现类

/**
 * 数据库类型
 * @author anqi
 */
public interface DataBase {
    /** 初始化数据库 */
    void init();
}
public class Mysql implements DataBase {
    @Override
    public void init() {
        System.out.println("MySQL初始化");
    }
}
public class Oracle implements DataBase{
    @Override
    public void init() {
        System.out.println("Oracle初始化");
    }
}
public class OceanBase implements DataBase{
    @Override
    public void init() {
        System.out.println("OceanBase初始化");
    }
}

消息队列接口及实现类

/**
 * 消息队列类型
 * @author anqi
 */
public interface Mq {
    /** 发送消息 */
    void sendMessage();
}
public class RabbitMQ implements Mq {
    @Override
    public void sendMessage() {
        System.out.println("使用RabbitMQ发送消息");
    }
}
public class KafkaMQ implements Mq {
    @Override
    public void sendMessage() {
        System.out.println("使用kafka发送消息");
    }
}

缓存接口及实现类

/**
 * 缓存类型
 * @author anqi
 */
public interface MyCache{
    /** 缓存数据 */
    void cacheData();
}
public class MemCache implements MyCache {
    @Override
    public void cacheData() {
        System.out.println("使用MemCache缓存");
    }
}
public class RedisCache implements MyCache {
    @Override
    public void cacheData() {
        System.out.println("使用redis缓存");
    }
}

抽象工厂类

/**
 * 抽象工厂类
 */
public abstract class AbstractSystemFac {
    public abstract MyCache useCache();
    public abstract Mq useMq();
    public abstract DataBase useDataBase();
}

具体工厂

public class SimpleSystemFac extends AbstractSystemFac {
    @Override
    public MyCache useCache() {
       return new MemCache();
    }

    @Override
    public Mq useMq() {
        return new RabbitMQ();
    }

    @Override
    public DataBase useDataBase() {
        return new Mysql();
    }
}

具体工厂

public class HugeSystemFac extends AbstractSystemFac {
    @Override
    public MyCache useCache() {
        return new RedisCache();
    }

    @Override
    public Mq useMq() {
        return new KafkaMQ();
    }

    @Override
    public DataBase useDataBase() {
        return new Oracle();
    }
}

测试类

public class TestDemo {
    public static void main(String[] args) {
        AbstractSystemFac simpleFac = new SimpleSystemFac();
        MyCache memcache = simpleFac.useCache();
        DataBase mysql = simpleFac.useDataBase();
        Mq rabbitmq = simpleFac.useMq();
        memcache.cacheData();;
        mysql.init();
        rabbitmq.sendMessage();

        AbstractSystemFac hugeFac = new HugeSystemFac();
        MyCache redis = hugeFac.useCache();
        DataBase oracle = hugeFac.useDataBase();
        Mq kafka = hugeFac.useMq();
        redis.cacheData();
        oracle.init();
        kafka.sendMessage();
    }
}
使用MemCache缓存
MySQL初始化
使用RabbitMQ发送消息
使用redis缓存
Oracle初始化
使用kafka发送消息

我们可以灵活地扩充一个新的产品RocketMQ,或者一个新的工厂类NewSystemFac,如下图所示

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SpringBoot使用拦截器、过滤器、监听器

    PS:原文链接https://www.cnblogs.com/haixiang/p/12000685.html,转载请注明出处

    海向
  • Centos7 下的防火墙端口配置

    查看所有打开的端口: firewall-cmd --zone=public --list-ports

    海向
  • 开闭原则——面向对象程序设计原则

    在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据 7 条原则来开发程序,从而提高软件开发效率、节约软件开发成本和...

    海向
  • 温故而知新:设计模式之抽象工厂(AbstractFactory)

    抽象工厂主要用来解决多个系列的对象实例问题。 问题的应用场景(来源于李建忠老师的webcast讲座): 如果有一款游戏,里面有"道路,房屋,隧道,丛林"这四类基...

    菩提树下的杨过
  • 温故而知新:设计模式之Builder

    Builder模式主要用于以下场景: 需要创建一个较复杂的大对象实例,并且构成该对象的子对象可能经常会发生变化,但是组成大对象的算法却相对稳定。 比如:我们做b...

    菩提树下的杨过
  • 桥接模式详解

    桥接(Bridge)模式的定义如下:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。 具体...

    提莫队长
  • 抽象工厂模式

    抽象工厂中 接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。 在简单工厂中,我们需要一辆车就用CarFact...

    OPice
  • 工厂模式

    在23中设计模式中,工厂方法属于创建型的设计模式,只有工厂方法和抽象工厂两种,但是实际我们常与简单工厂混淆,因为简单工厂模式违背了开闭原则。

    胖虎
  • Java内功心法,行为型设计模式

    使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。

    李红
  • IOC编程

    2. 开放/封闭原则: 添加任何新行为,应该是扩展到新类中,而不应该直接修改原来运行良好的代码。

    小蜜蜂

扫码关注云+社区

领取腾讯云代金券