一、引入两个新概念

产品等级结构:即产品的继承结构。例如:抽象产品(父类)是电视机,具体产品(子类)是海尔电视机、海信电视机、TCL电视机等。二者之间构成一个产品等级结构。

产品族:共一个工厂生产的产品,位于不同产品等级结构中的一组产品。比如海尔工厂 不仅生产海尔电视机,还生产海尔空调、海尔口红、海尔洗发水等。


二、抽象工厂模式也是创建型模式,角色和工厂方法模式一样,但功能有所差异。

1.抽象工厂

声明生成抽象产品的方法,在一个抽象工厂中可以定义一组方法,每一个方法对应一个产品等级结构。

2.具体工厂

实现抽象工厂中的方法,生产一组产品,这些产品构成一个产品族,每一个产品都位于某个产品等级结构中。

3.抽象产品

定义产品公有的业务方法。

4.具体产品

实现抽象产品中的方法。


三、代码测试

抽象工厂类EFactory:有生产产品的抽象方法

package abstract_factory;

public interface EFactory {
    public TV produceTV();
    public Air produceAir();
}
EFactory

抽象产品类TV和Air:有各自的抽象方法

package abstract_factory;

public interface TV {
    public void play();
}
TV
package abstract_factory;

public abstract class Air {//抽象产品类
    public abstract void change();
}
Air

具体工厂:TCLFactory和HaierFactory

package abstract_factory;

public class TCLFactory implements EFactory{
    public TV produceTV() {
        return new TCLTV();
    }
    public Air produceAir() {
        return new TCLAir();
    }
}
TCLFactory
package abstract_factory;

public class HaierFactory implements EFactory {

    public TV produceTV() {
        return new HaierTV();
    }

    public Air produceAir() {
        return new HaierAir();
    }
}
HaierFactory

具体产品:HaierTV 、HaierAir、 TCLTV 、TCLAir

package abstract_factory;

public class HaierTV implements TV {
    public void play() {
        System.out.println("具体产品类海尔电视机");
    }
}
HaierTV
package abstract_factory;

public class HaierAir extends Air{
    public void change() {
        System.out.println("具体产品类:海尔空调");
    }
}
HaierAir
package abstract_factory;

public class TCLTV implements TV {
    public void play() {
        System.out.println("具体产品类TCL电视机");
    }
}
TCLTV
package abstract_factory;

public class TCLAir extends Air{
    public void change() {
        System.out.println("具体产品类TCL空调");
    }
}
TCLAir

模拟DAO层:

package abstract_factory;

import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
import java.net.URL;

public class XMLUtil {

    public static Object getBean() {
        try {
            //创建DOM文档对象
            DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();//文档制造者工厂创建了一个 文档制造者工厂对象
            DocumentBuilder builder=dFactory.newDocumentBuilder();//文档制造者类 通过 文档制造者工厂 创造一个 文档制造者对象
            Document doc;//文档制造者 创建 文档
            doc=builder.parse(new File("src/abstract_factory/TV.xml"));//解析xml文件

            //获取包含类名的文本节点
            NodeList nl=doc.getElementsByTagName("className");//文本节点列表里有很多被className标签夹着的内容
            Node classNode=nl.item(0).getFirstChild();
            //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;
        }
    }
}
XMLUtil
<?xml version="1.0"?>
<config>
    <className>abstract_factory.TCLFactory</className>
</config>
TV.XML

<className>标签里有的书是直接写类名,已经弃用,现在写法是:包名.类名

客户端:制造产品

package abstract_factory;

public class Client {

    public static void main(String[] args) {
        try {
            EFactory factory;
            TV tv;
            Air air;//抽象类定义 抽象工厂对象,抽象电视机,抽象空调
            factory=(EFactory)XMLUtil.getBean();//获取具体工厂
            tv=factory.produceTV();//接下来通过具体工厂得到产品,具体是啥咱也不知道咱也不敢问
            tv.play();
            air=factory.produceAir();
            air.change();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}
Client
02-01 07:34