一、引入两个新概念
产品等级结构:即产品的继承结构。例如:抽象产品(父类)是电视机,具体产品(子类)是海尔电视机、海信电视机、TCL电视机等。二者之间构成一个产品等级结构。
产品族:共一个工厂生产的产品,位于不同产品等级结构中的一组产品。比如海尔工厂 不仅生产海尔电视机,还生产海尔空调、海尔口红、海尔洗发水等。
二、抽象工厂模式也是创建型模式,角色和工厂方法模式一样,但功能有所差异。
1.抽象工厂
声明生成抽象产品的方法,在一个抽象工厂中可以定义一组方法,每一个方法对应一个产品等级结构。
2.具体工厂
实现抽象工厂中的方法,生产一组产品,这些产品构成一个产品族,每一个产品都位于某个产品等级结构中。
3.抽象产品
定义产品公有的业务方法。
4.具体产品
实现抽象产品中的方法。
三、代码测试
抽象工厂类EFactory:有生产产品的抽象方法
package abstract_factory; public interface EFactory { public TV produceTV(); public Air produceAir(); }
抽象产品类TV和Air:有各自的抽象方法
package abstract_factory; public interface TV { public void play(); }
package abstract_factory; public abstract class Air {//抽象产品类 public abstract void change(); }
具体工厂:TCLFactory和HaierFactory
package abstract_factory; public class TCLFactory implements EFactory{ public TV produceTV() { return new TCLTV(); } public Air produceAir() { return new TCLAir(); } }
package abstract_factory; public class HaierFactory implements EFactory { public TV produceTV() { return new HaierTV(); } public Air produceAir() { return new HaierAir(); } }
具体产品:HaierTV 、HaierAir、 TCLTV 、TCLAir
package abstract_factory; public class HaierTV implements TV { public void play() { System.out.println("具体产品类海尔电视机"); } }
package abstract_factory; public class HaierAir extends Air{ public void change() { System.out.println("具体产品类:海尔空调"); } }
package abstract_factory; public class TCLTV implements TV { public void play() { System.out.println("具体产品类TCL电视机"); } }
package abstract_factory; public class TCLAir extends Air{ public void change() { System.out.println("具体产品类TCL空调"); } }
模拟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; } } }
<?xml version="1.0"?> <config> <className>abstract_factory.TCLFactory</className> </config>
<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()); } } }