抽象工厂模式详解(四)

一、定义

        为创建一组相关或者相互依赖的对象提供一个接口,而且无须指定它们的具体类。

        简单的说,抽象工厂模式是工厂方法模式的升级版本,当存在多个产品族时,产品族之间是存在相关或者依赖关系,可以使用抽象工厂来创建产品。

二、实例分析

        网上已经有很多关于宝马的抽象工厂的例子了,这里我们不在累述。抽象工厂的起源或是更早的应用,是为了用于创建分属于不同操作系统的视窗构建,如按钮(Button)、文本(Text)等等。我们来分析另一个例子:

        例如一个应用,需要在不同平台(Windows、Linux)上运行,你会怎么设计?分别设计俩套不同应用?非也,通过抽象工厂模式屏蔽掉操作系统对应用的影响。软件功能、逻辑、UI 都一个非常类似,唯一的不同是调用不同的工厂方法,由不同的产品类去处理与操作系统交互的信息。

1.产品族

        产品族是一组存在相关关系的对象,上例中,我们存在两个产品族,一个是Windows 产品族,另一个是 Linux 产品族。即

public interface IWindowProduct {
}
 
public interface ILinuxProduct {
}

        假设现在我们有两个具体的产品,按钮和文本,那么

public class WindowsButton implements IWindowProduct {
    public WindowsButton() {
        System.out.println("create a Windows button");
    }
}
 
public class WindowsText implements IWindowProduct {
    public WindowsText() {
        System.out.println("create a Windows text");
    }
}
 
public class LinuxButton implements ILinuxProduct {
    public LinuxButton() {
        System.out.println("create a Linux button");
    }
}
 
public class LinuxText implements ILinuxProduct {
    public LinuxText() {
        System.out.println("create a Linux text");
    }
}

2.工厂

        首先我们可以定义一个工厂的接口,约束它能够生产些什么

public interface IFactory {
    <T1 extends IWindowProduct> T1 createWindowProduct(Class<T1> cls); 
    <T2 extends ILinuxProduct> T2 createLinuxProduct(Class<T2> cls);
}

        其次我们实现这个接口,完成具体的创建逻辑

public class ProductFactory implements IFactory {
 
    public <T1 extends IWindowProduct> T1 createWindowProduct(Class<T1> cls) {
        T1 windowProduct = null;
        try {
            windowProduct = (T1) Class.forName(cls.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("createWindowProduct failed! exception: " + e.toString());
        }
        return windowProduct;
    }
 
    public <T2 extends ILinuxProduct> T2 createLinuxProduct(Class<T2> cls) {
        T2 linuxProduct = null;
        try {
            linuxProduct = (T2) Class.forName(cls.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("createLinuxProduct failed! exception: " + e.toString());
        }
        return linuxProduct;
    }
 
}

3.场景

public class Client {
 
    public static void main(String[] args) {
        ProductFactory productFactory = new ProductFactory();
 
        // 制造 Button
        WindowsButton windowsButton = productFactory.createWindowProduct(WindowsButton.class);
        LinuxButton linuxButton = productFactory.createLinuxProduct(LinuxButton.class);
 
        // 制造 Text
        WindowsText windowsText = productFactory.createWindowProduct(WindowsText.class);
        LinuxText linuxText = productFactory.createLinuxProduct(LinuxText.class);
         
        // 具体的逻辑和交互由具体的产品类负责
    }
}
        运行结果为:
create a Windows button
create a Linux button
create a Windows text
create a Linux text
三、通用源码类图分析

        

        其中 AbstractProductA 和 AbstractProductB 就是两个产品族抽象,例如 Windows 产品族和 Linux产品族。而 Product1 和 Product2 就是产品族下的具体产品类,例如 Button、Text、Image 等等。AbstractCreator 就是工厂的抽象。

四、抽象工厂特点

1.和工厂方法一样,具有良好的封装性,抽象工厂是工厂方法的升级形式。

2.横向扩展容易。例如增加一个 Image,我们只需要创建两个具体的产品类 WindowsImage 和 LinuxImage,然后由工厂创建即可。

3.纵向扩展困难。例如添加一个新的产品族 Android,AbstractCreator 就需要对应增加一个 createAndroidProduct(),如果抽象工厂存在多个子类,那么其所有子类也都要随之更改,严重违背开闭原则。


查看更多:设计模式分类以及六大设计原则

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值