设计模式__抽象工厂模式

定义

抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

之前的工厂模式所创建的对象是同一类的,一个类型的工厂就可以呃,现在需要不同类型的产品,需要大范围的工厂产生小工厂,小工厂再来生产产品。

当每个抽象产品都有多于一个的具体子类的时候,工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产品 角色都有两个具体产品。抽象工厂模式提供两个具体工厂角色,分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。
每一个模式都是针对一定问题的解决方案,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式针对的是多个产品等级结构。

抽象工厂模式通常适用于以下场景:

  1. 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
  2. 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
  3. 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

工厂模式和抽象工厂模式的模型
在这里插入图片描述在这里插入图片描述
现在很容易看出区别

产品族(liaojie)

是指位于不同产品等级结构中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。显然,每一个产品族中含有产品的数目,与产品等级结构的数目是相等的,形成一个二维的坐标系,水平坐标是产品等级结构,纵坐标是产品族。叫做相图。

当有多个不同的等级结构的产品时,如果使用工厂方法模式就势必要使用多个独立的工厂等级结构来对付这些产品的等级结构。如果这些产品等级结构是平行的,会导致多个平行的工厂等级结构。
抽象工厂模式使用同一个 工厂等级结构负责这些不同产品等级结构产品对象的创建。
对于每一个产品族,都有一个具体工厂。而每一个具体工厂创建属于同一个产品族,但是分属于不同等级结构的产品。
通过引进抽象工厂模式,可以处理具有相同(或者相似)等级结构的多个产品族中的产品对象的创建问题。

由于每个具体工厂角色都需要负责两个不同等级结构的产品对象的创建,因此每个工厂角色都需要提供两个工厂方法,分别用于创建两个等级结构的产品。既然每个具体工厂角色都需要实现这两个工厂方法,所以具有一般性,不妨抽象出来,移动到抽象工厂角色中加以声明。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

这里有两个说法

  1. 来自http://c.biancheng.net/view/1351.html 一个工厂生产一个产品族。
  2. 来自菜鸟教程 一个大工厂产生小工厂,小工厂产生产品。抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。

可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
当增加一个新的产品族时不需要修改原代码,满足开闭原则。
其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

模式的结构与实现

  1. 模式的结构

抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它 同具体工厂之间是多对一的关系。

可以看出抽象工厂模式的结构同工厂方法模式的结构相似,不同的是其产品的种类不止一个,所以创建产品的方法也不止一个。下面给出抽象工厂和具体工厂的代码。

第一种实现代码

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

    public interface Television
    {
    	public void play();
    }

public interface AirConditioner
{
	public void changeTemperature();
}

public class HaierFactory implements EFactory
{
	public Television produceTelevision()
	{
		return new HaierTelevision();
	}
	
	public AirConditioner produceAirConditioner()
	{
		return new HairAirConditioner();
	}
}
public class HaierTelevision implements Television
{
	public void play()
	{
		System.out.println("海尔电视机播放中......");
	}
}
public class HairAirConditioner implements AirConditioner
{
	public void changeTemperature()
	{
		System.out.println("海尔空调温度改变中......");
	}
}

public class TCLFactory implements EFactory
{
	public Television produceTelevision()
	{
		return new TCLTelevision();
	}
	
	public AirConditioner produceAirConditioner()
	{
		return new TCLAirConditioner();
	}
}
public class TCLAirConditioner implements AirConditioner
{
	public void changeTemperature()
	{
		System.out.println("TCL空调温度改变中......");
	}
}
public class TCLTelevision implements Television
{
	public void play()
	{
		System.out.println("TCL电视机播放中......");
	}
}

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());
         }
	}
}
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
public class XMLUtil
{
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
	public static Object getBean()
	{
		try
		{
			//创建文档对象
			DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = dFactory.newDocumentBuilder();
			Document doc;							
			doc = builder.parse(new File("config.xml")); 
		
			//获取包含类名的文本节点
			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;
           	}
		}
}

![在这里

第二种实现代码–详细看菜鸟教程----这里就不写了

猜你喜欢

转载自blog.csdn.net/qq_40803626/article/details/88593256
今日推荐