第三章 设计模式--工厂模式 之抽象工厂模式

抽象工厂模式

定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口。

适用场景:
1、客户端不依赖与产品类实例如何被创建、实现等细节
2、强调一系列相关产品对象(属于同一产品族),一起适用创建对象需要大量重复代码。
3、提供一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖于具体实现。

优点:
1、代码隔离,我虚关心具体实现细节。
2、将一系列的产品族统一到一起创建。

缺点:
1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
2、增加了系统的抽象性和理解难度。

下面来一下,抽象工厂中的 产品等级结构和产品族

在这里插入图片描述
这个图主要描述了,产品族和产品等级结构的联系和区别:

产品族:主要表示一个类中包含多个方法或属性。
产品等级结构:主要表示多个类中相同的 方法或属性。

我们可以举例来看,例如:

联想公司的产品可以生产联想电脑,也可以生产联想软件,也可以生产联想 洗衣机。
惠普公司的产品可以生产惠普电脑,也可以生产惠普软件,也可以生产惠普 洗衣机。
在上述中 联想公司的 3 个产品(电脑、软件、洗衣机)就是产品族;联想公司的电脑、惠普公司的电脑 属于一类产品,属于同一个产品等级结构。

下面我们用代码来模拟 抽象工厂模式:

1、抽象工厂及其实现的2个子类:

抽象工厂类:
/**
 * @program: adpn-pattern->ComputerFactory
        * @description: 生产电脑工厂类
        * @author: Jstar
        * @create: 2019-11-17 11:34
        **/
public abstract  class ComputerFactory {
    public abstract Software getSoftware();
    public abstract Computer getComputer();
}
联想工厂类:
public class ThinkpadComputerFactory extends ComputerFactory {
    @Override
    public Software getSoftware() {
        return new ThinkpadSoftware();
    }
    @Override
    public Computer getComputer() {
        return new ThinkpadComputer();
    }
}
惠普工厂类:
public class HpComputerFactory extends ComputerFactory {
    @Override
    public Software getSoftware() {
        return new HpSoftware();
    }
    @Override
    public Computer getComputer() {
        return new HpComputer();
    }
}

2、电脑抽象类及其实现的2个子类:

电脑抽象类:
/**
 * @program: adpn-pattern->Computer
 * @description: 电脑类
 * @author: Jstar
 * @create: 2019-11-17 11:18
 **/
public abstract class Computer {
    public abstract void process();
}
联想电脑:
public class ThinkpadComputer extends Computer {
    @Override
    public void process() {
        System.out.println("这里可写业务代码,但我们模拟--生产联想电脑");
    }
}
惠普电脑:
public class HpComputer extends Computer {
    @Override
    public void process() {
        System.out.println("这里可写业务代码,但我们模拟--生产惠普电脑");
    }
}

3、软件 抽象类及其实现的2个子类:

软件抽象类:
/**
 * @program: adpn-pattern->Software
 * @description:
 * @author: Jstar
 * @create: 2019-11-17 20:58
 **/
public abstract class Software {
    public abstract void process();
}
联想软件:
public class ThinkpadSoftware extends Software {
    @Override
    public void process() {
        System.out.println("这里可写业务代码,但我们模拟--生产联想--软件");
    }
}
惠普软件:
public class HpSoftware extends Software {
    @Override
    public void process() {
        System.out.println("这里可写业务代码,但我们模拟--生产惠普--软件");
    }
}

4、下面我们来模拟一下客户端调用:

/**
 * @program: adpn-pattern->Test
 * @description: 测试类
 * @author: Jstar
 * @create: 2019-11-17 11:42
 **/
public class Test {
    public static void main(String[] args) {
        ComputerFactory thinkpadComputerFactory = new ThinkpadComputerFactory();
        Computer computer = thinkpadComputerFactory.getComputer();
        Software software = thinkpadComputerFactory.getSoftware();
        computer.process();
        software.process();
        System.out.println("------两种产品族-----分割线");
        HpComputerFactory hpComputerFactory = new HpComputerFactory();
        Computer computer1 = hpComputerFactory.getComputer();
        Software software1 = hpComputerFactory.getSoftware();
        computer1.process();
        software1.process();
    }
}

5、运行测试类的结果:

这里可写业务代码,但我们模拟--生产联想电脑
这里可写业务代码,但我们模拟--生产联想--软件
------两种产品族-----分割线
这里可写业务代码,但我们模拟--生产惠普电脑
这里可写业务代码,但我们模拟--生产惠普--软件

从结果看,两个工厂产品族互不影响,各自完成生产电脑和生产软件的方法,没有出现交叉的问题。

我们来看一下上述代码的UML图调用关系:
在这里插入图片描述

功能扩展:

假如我们想扩展一个苹果的厂商生产产品,即扩展一个产品族。我们只需在原来的基础上做横向扩展即可,即添加苹果工厂的实现类,苹果生产电脑的类,苹果生产软件的类,在客户端做调用即可, 不影响之前的功能,满足开闭原则。
但是如果我们想扩展,一个生产洗衣机的功能,这个在上述的模拟中就很难实现了,需要在工厂接口中添加 获取洗衣机的方法,且该接口的每个实现都得进行改动,有很大的侵入性,违背了 开闭原则。
所以,一类的模式有它的优点,也有它存在的不足,使用时要根据实际的业务场景进行使用。

抽象工厂在jdk源码中的使用:

1、java.sql.Connection 是数据库的连接接口,我们从接口中可以看到

在这里插入图片描述
从图中我们可以看到,不论方法是 返回 Statement 还是 PreparedStatement ,这两者都属于一个产品族。

2、再来看一下,mybatis 中的 SqlSessionFactory ,是如何创建 SqlSession的。

在这里插入图片描述
可以看到抽象工厂中也是返回了两种产品,属于一个产品族。
在这里插入图片描述
可以看到,返回的是 抽象的 SqlSession ,但具体的实现是 DefaultSqlSession ,这是典型的抽象工厂模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值