目 录CONTENT

文章目录

抽象工厂模式

半糖
2024-08-16 / 0 评论 / 0 点赞 / 84 阅读 / 14336 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2024-08-21,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

名称

抽象工厂模式(ABSTRACT FACTORY),别名:Kit

目的

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

适用性

在以下情况可以使用Abstract Factory模式

  • 一个系统要独立于它的产品的创建、组合和表示时。

  • 一个系统要由多个产品系列中的一个来配置时。

  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。

  • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。

结构

抽象工厂(AbstractFactory):声明一个创建抽象产品对象的操作接口。

具体工厂(ConcreteFactory):实现创建具体产品对象的操作。实现AbstractFactory接口。

抽象产品(AbstractProduct):为一类产品对象声明一个接口。

具体产品(ConcreteProduct):定义一个将被相应的具体工厂创建的产品对象。实现AbstractProduct接口。

客户端(Client):仅使用由AbstractFactory和AbstractProduct类声明的接口。

协作

  1. 通常在运行时刻创建一个ConcreteFactroy类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应使用不同的具体工厂。

  2. AbstractFactory将产品对象的创建延迟到它的ConcreteFactory子类。

效果

优点

  1. 分离了具体的类。将客户与类的实现分离,客户通过它们的抽象接口操纵实例。产品的类名也在具体工厂的实现中被分离;它们不出现在客户代码中。

  2. 易于交换产品系列。一个具体工厂类在一个应用中仅出现一次(初始化时),这使得改变一个应用的具体工厂更加容易,只需改变具体工厂即可使用不同的产品系列。这是因为一个抽象工厂创建了一个完整的产品系列,所以整个产品系列会立刻改变。

  3. 有利于产品的一致性。当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,抽象工厂很容易实现这一点。

缺点

  1. 难以支持新种类的产品。AbstractFactory接口确定了可以被创建的产品集合,支持新种类的产品就需要扩展该工厂接口,这将涉及AbstractFactory类及其所有子类的改变

应用

问题

我们在使用浏览器的时候可以设置浏览器的外观(比如下图的谷歌浏览器设置),当切换外观的时候背景、按钮等组件都会有不同的展示。此时我们想要设计一款浏览器,分别有春天和夏天两种外观,当切换外观时,浏览器的按钮、文本框、组合框会有不同的展示,此时外观就对应着我们的抽象工厂,春天和夏天外观对应着具体工厂,按钮、文本框、组合框对应着抽象产品,春天和夏天的按钮、文本框、组合框就是我们的具体产品。

示例

UML

代码示例

抽象工厂:外观工厂接口,定义三个抽象产品的方法createButton、createTextField、createComboBox

package com.ysj.part3.abstractFactory.abstractFactory;


import com.ysj.part3.abstractFactory.abstractProduct.Button;
import com.ysj.part3.abstractFactory.abstractProduct.ComboBox;
import com.ysj.part3.abstractFactory.abstractProduct.TextField;

//界面皮肤工厂接口:抽象工厂
public interface SkinFactory {
    public Button createButton();
    public TextField createTextField();
    public ComboBox createComboBox();
}

抽象产品:按钮、文本框、组合框,定义接口方法display

package com.ysj.part3.abstractFactory.abstractProduct;

//在本实例中我们对代码进行了大量简化,实际使用时,界面组件的初始化代码较为复杂,还需要使用JDK中一些已有类,为了突出核心代码,在此只提供框架代码和演示输出。
//按钮接口:抽象产品
public interface Button {
    public void display();
}

package com.ysj.part3.abstractFactory.abstractProduct;

//文本框接口:抽象产品
public interface TextField {
    public void display();
}
package com.ysj.part3.abstractFactory.abstractProduct;

//组合框接口:抽象产品
public interface ComboBox {
    public void display();
}

具体工厂:春天、夏天外观具体工厂,实现抽象工厂SkinFactory

package com.ysj.part3.abstractFactory.concreteFactory;

import com.ysj.part3.abstractFactory.abstractFactory.SkinFactory;
import com.ysj.part3.abstractFactory.abstractProduct.Button;
import com.ysj.part3.abstractFactory.abstractProduct.ComboBox;
import com.ysj.part3.abstractFactory.abstractProduct.TextField;
import com.ysj.part3.abstractFactory.concreteProduct.SpringButton;
import com.ysj.part3.abstractFactory.concreteProduct.SpringComboBox;
import com.ysj.part3.abstractFactory.concreteProduct.SpringTextField;

//Spring皮肤工厂:具体工厂
public class SpringSkinFactory implements SkinFactory {
    public Button createButton() {
        return new SpringButton();
    }

    public TextField createTextField() {
        return new SpringTextField();
    }

    public ComboBox createComboBox() {
        return new SpringComboBox();
    }
}
package com.ysj.part3.abstractFactory.concreteFactory;

import com.ysj.part3.abstractFactory.concreteProduct.SummerButton;
import com.ysj.part3.abstractFactory.concreteProduct.SummerComboBox;
import com.ysj.part3.abstractFactory.concreteProduct.SummerTextField;
import com.ysj.part3.abstractFactory.abstractFactory.SkinFactory;
import com.ysj.part3.abstractFactory.abstractProduct.Button;
import com.ysj.part3.abstractFactory.abstractProduct.ComboBox;
import com.ysj.part3.abstractFactory.abstractProduct.TextField;

//Summer皮肤工厂:具体工厂
public class SummerSkinFactory implements SkinFactory {
    public Button createButton() {
        return new SummerButton();
    }

    public TextField createTextField() {
        return new SummerTextField();
    }

    public ComboBox createComboBox() {
        return new SummerComboBox();
    }
}

具体产品:春天、夏天外观的具体产品按钮、文本框、组合框,实现各自的抽象产品

package com.ysj.part3.abstractFactory.concreteProduct;

import com.ysj.part3.abstractFactory.abstractProduct.Button;

//Spring按钮类:具体产品
public class SpringButton implements Button {
    public void display() {
        System.out.println("显示浅绿色按钮。");
    }
}

package com.ysj.part3.abstractFactory.concreteProduct;

import com.ysj.part3.abstractFactory.abstractProduct.ComboBox;

//Spring组合框类:具体产品
public class SpringComboBox implements ComboBox {
    public void display() {
        System.out.println("显示绿色边框组合框。");
    }
}

package com.ysj.part3.abstractFactory.concreteProduct;

import com.ysj.part3.abstractFactory.abstractProduct.TextField;

//Spring文本框类:具体产品
public class SpringTextField implements TextField {
    public void display() {
        System.out.println("显示绿色边框文本框。");
    }
}

package com.ysj.part3.abstractFactory.concreteProduct;

import com.ysj.part3.abstractFactory.abstractProduct.Button;

//Summer按钮类:具体产品
public class SummerButton implements Button {
    public void display() {
        System.out.println("显示浅蓝色按钮。");
    }
}

package com.ysj.part3.abstractFactory.concreteProduct;

import com.ysj.part3.abstractFactory.abstractProduct.ComboBox;

//Summer组合框类:具体产品
public class SummerComboBox implements ComboBox {
    public void display() {
        System.out.println("显示蓝色边框组合框。");
    }
}  

package com.ysj.part3.abstractFactory.concreteProduct;

import com.ysj.part3.abstractFactory.abstractProduct.TextField;

//Summer文本框类:具体产品
public class SummerTextField implements TextField {
    public void display() {
        System.out.println("显示蓝色边框文本框。");
    }
}

使用到的工具类:从xml中解析内容

package com.ysj.common.utils;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;

public class XMLUtil {
    //该方法用于从XML配置文件中提取图表类型,并返回类型名
    public static String getChartType() {
        try {
            //创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File(String.class.getResource("/config.xml").getPath()));

            //获取包含图表类型的文本节点
            NodeList nl = doc.getElementsByTagName("chartType");
            Node classNode = nl.item(0).getFirstChild();
            String chartType = classNode.getNodeValue().trim();
            return chartType;
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
    public static Object getBean(String className) {
        try {
            //创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File(String.class.getResource("/config.xml").getPath()));

            //获取包含类名的文本节点
            NodeList nl = doc.getElementsByTagName(className);
            Node classNode=nl.item(0).getFirstChild();
            String cName=classNode.getNodeValue();

            //通过类名生成实例对象并将其返回
            Class c=Class.forName(cName);
            Object obj=c.newInstance();
            return obj;
        }
        catch(Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

xml:config.xml

<?xml version="1.0"?>
<config>
    <summerSkin>com.ysj.part3.abstractFactory.concreteFactory.SummerSkinFactory</summerSkin>
    <springSkin>com.ysj.part3.abstractFactory.concreteFactory.SpringSkinFactory</springSkin>
</config>

客户端:Client

package com.ysj.part3.abstractFactory;


import com.ysj.common.utils.XMLUtil;
import com.ysj.part3.abstractFactory.abstractFactory.SkinFactory;
import com.ysj.part3.abstractFactory.abstractProduct.Button;
import com.ysj.part3.abstractFactory.abstractProduct.ComboBox;
import com.ysj.part3.abstractFactory.abstractProduct.TextField;

/**
 * 抽象工厂模式
 * 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
 */
class Client {
    public static void main(String args[]) {
        //使用抽象层定义
        SkinFactory factory;
        Button bt;
        TextField tf;
        ComboBox cb;
        factory = (SkinFactory) XMLUtil.getBean("springSkin");
        bt = factory.createButton();
        tf = factory.createTextField();
        cb = factory.createComboBox();
        bt.display();
        tf.display();
        cb.display();
    }
}

已知应用

java Swing/AWT

提供了不同的Look and Feel(外观与感觉)抽象工厂,如MetalLookAndFeel, MotifLookAndFeel等,这些工厂负责创建特定风格的GUI组件。

spring Framework

spring的核心是IOC容器,其中BeanFactory 接口是所有IOC容器的基础,它提供了创建和管理 Bean 的通用方法。

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区