完整案例分析再加知识整合——艾特抽象工厂模式,超详细的

2020-04-15 18:17:22 浏览数 (1)

抽象工厂模式

模式动机与定义

模式动机
  • 产品等级结构:产品等级结构即产品的继承结构,例如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
  • 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,例如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。
模式定义
  • 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

模式结构与分析

模式结构

抽象工厂模式包含如下角色:

  • AbstractFactory:抽象工厂
  • ConcreteFactory:具体工厂
  • AbstractProduct:抽象产品
  • ConcreteProduct:具体产品
模式分析

模式实例与解析

模式实例

电器工厂:实例说明

  • 一个电器工厂可以生产多种类型的电器,如海尔工厂可以生产海尔电视机、海尔空调等,TCL工厂可以生产TCL电视机、TCL空调等,相同品牌的电器构成一个产品族,而相同类型的电器构成了一个产品等级结构,现使用抽象工厂模式模拟该场景。

电器工厂:参考类图

电器工厂:参考代码

代码结构

Television接口

代码语言:javascript复制
package abstractfactory;

public interface Television {
    public void play();
}

HaierTelevision类

代码语言:javascript复制
package abstractfactory;

public class HaierTelevision implements Television {
    @Override
    public void play() {
        System.out.println("海尔电视机播放中···");
    }
}

TCLTelevision类

代码语言:javascript复制
package abstractfactory;

public class TCLTelevision implements Television {
    @Override
    public void play() {
        System.out.println("TCL电视机播放中···");
    }
}

AirConditioner接口

代码语言:javascript复制
package abstractfactory;

public interface AirConditioner {
    public void changeTemperature();
}

HaierAirConditioner类

代码语言:javascript复制
package abstractfactory;

public class HaierAirConditioner implements AirConditioner {
    @Override
    public void changeTemperature() {
        System.out.println("海尔空调温度改变中···");
    }
}

TCLAirConditioner类

代码语言:javascript复制
package abstractfactory;

public class TCLAirConditioner implements AirConditioner {
    @Override
    public void changeTemperature() {
        System.out.println("TCL空调温度改变中···");
    }
}

EFactory接口

代码语言:javascript复制
package abstractfactory;

public interface EFactory {
    public Television produceTelevision();
    public AirConditioner produceAirConditioner();
}

HaierFactory类

代码语言:javascript复制
package abstractfactory;

public class HaierFactory implements EFactory {
    @Override
    public Television produceTelevision() {
        return new HaierTelevision();
    }

    @Override
    public AirConditioner produceAirConditioner() {
        return new HaierAirConditioner();
    }
}

TCLFactory类

代码语言:javascript复制
package abstractfactory;

public class TCLFactory implements EFactory {
    @Override
    public Television produceTelevision() {
        return new TCLTelevision();
    }

    @Override
    public AirConditioner produceAirConditioner() {
        
        return new TCLAirConditioner();
    }
}

AbstractFactoryconfig.xml

代码语言:javascript复制
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>abstractfactory.HaierFactory</className>

</config>

XMLUtil类

代码语言:javascript复制
package abstractfactory;

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 Object getBean(){
        try {
            //创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;

            doc = builder.parse(new File("D:\MyNewWorld\Study_JAVA\MyHome\Write_java\My_Maven\src\main\resources\AbstractFactoryconfig.xml"));


            //获取包含类名的文本节点
            NodeList n1 = doc.getElementsByTagName("className");
            Node classNode = n1.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;
        }
    }
}

Client类

代码语言:javascript复制
package abstractfactory;

public class Client {
    public static void main(String[] args) {
        try{

            EFactory factory;
            Television tv;
            AirConditioner ac;

            factory = (EFactory) XMLUtil.getBean();
            tv = factory.produceTelevision();
            tv.play();

            ac = factory.produceAirConditioner();
            ac.changeTemperature();
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}

运行结果

模式效果与应用

抽象工厂模式优点:

  • 隔离了具体类的生成,使得客户端并不需要知道什么被创建
  • 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象
  • 增加新的产品族很方便,无需修改已有系统,符合开闭原则

抽象工厂模式缺点:

  • 增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则

在以下情况下可以使用抽象工厂模式:

  • 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节
  • 系统中有多于一个的产品族,但每次只使用其中某一产品族
  • 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
  • 产品等级结构稳定,在设计完成之后不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。

0 人点赞