简单工厂、工厂方法模式和抽象工厂(实例)

一、简单工厂

简单工厂是一种类创建型模式,它又称静态工厂方法。在简单工厂模式中,可以根据参数的不同来返回不同类的实例。

1、模式结构

在这里插入图片描述Factory:工厂角色,负责实现创建所有实例的内部逻辑,外部通过调用factoryMethod创建产品对象。
Product:抽象产品角色,所有具体产品的抽象父类。
ConcreteProduct:具体产品角色。

2、模式实例

一个汽车生产商承接了各种品牌汽车的生产,当为宝马汽车生产产品时只需要在调用该工厂的方法时传入参数“BM”即可创建相应产品,现用简单模式来模拟实现。

2.1 代码实现

(1)Car.java

public interface Car {
	public void run();
}

(2)宝马工厂类:BMFactory.java

public class BMFactory implements Car{
	@Override
	public void run() {
		System.out.println("宝马汽车疾驰中......");
	}
}

(3)奔驰工厂类:BCFactory.java

public class BCFactory implements Car {
	@Override
	public void run() {
		System.out.println("奔驰汽车飞驰中...");
	}
}

(4)创建工厂类CarFactory.java

public class CarFactory {
	public static Car productCar(String brand) throws Exception{
		if(brand.equals("BM")){
			System.out.println("汽车工厂生产宝马汽车...");
			return new BMFactory();
		}else if(brand.equals("BC")){
			System.out.println("汽车工厂生产奔驰汽车...");
			return new BCFactory();
		}else{
			throw new Exception("工厂暂时无法生产该汽车");
		}
		
	}
}

(5) 客户端调用工厂类Client.java

public class Client {
	public static void main(String[] args) {
		try
        {
			Car car;
			String brand = XMLUtil.getBrandName();
			car = CarFactory.productCar(brand);
			car.run();
        }
        catch(Exception e)
        {
        	System.out.println(e.getMessage());
        }
	}
}

(6)XMLUtil.java
该类用于读取XML配置文件中的信息,并且进行实例化,该类的getBean方法用于从XML配置文件中提取品牌名称,并返回该品牌名称。这样的好处是需要修改产品信息时只需要修改XML配置文件中的信息,而无需修改代码。

public class XMLUtil {

	    //该方法用于从XML配置文件中提取品牌名称,并返回该品牌名称
		public static String getBrandName()
		{
			try
			{
				/*
				 * javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象 , 
				 * DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法 ,
				 * 这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
				 */
				//创建文档对象
				DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();  //得到一个创建DOM解析器的工厂
				DocumentBuilder builder = dFactory.newDocumentBuilder();  //DOM解析器对象
				Document doc;							
				doc = builder.parse(new File("./config/simpleFactory.xml")); //DOM解析器解析xml文件得到代表整个文档的Document对象
			
				//获取包含品牌名称的文本节点
				NodeList nl = doc.getElementsByTagName("carBrand");  //获得carBrand元素节点  
	            Node classNode=nl.item(0).getFirstChild();  //获得第一个
	            String brandName=classNode.getNodeValue().trim();  //获得carBrand节点的属性值
	            return brandName;
	           }   
	           	catch(Exception e)
	          {
	           	e.printStackTrace();
	           	return null;
	         }
		}

}

(7)XML配置文件:simpleFactory.xml

<config>
	<carBrand>BM</carBrand>
</config>

3、模式分析

简单工厂模式可以降低系统的耦合度,在调用工厂类的工厂方法时,只需要传入一个简单的参数而无需知道具体的对象创建的细节,将参数保存在XML等配置文件中,在修改时无需修改java源码。

3.1 优点

简单工厂模式实现了对象的创建和使用的分离,创建时客户端无需知道具体产品的创建细节,只需传入参数即可,在一定程度上提高了系统的灵活性。

3.2 缺点

简单模式的缺点很明显,工厂类集中了系统中所有产品的创建逻辑,职责较为沉重,而增添新产品时,必须要修改工厂。

3.3 适用场景

简单工厂模式适用于工厂类负责创建的对象较少时,这样不会造成工厂方法中的业务逻辑过于复杂。

二、工厂方法

工厂方法模式简称工厂模式,是一种类创建型模式,工厂方法针对的是多个产品系列结构,是java中最常用的设计模式之一,是简单工厂的衍生,它符合开闭原则,实现了可扩展性。

1、模式结构

在这里插入图片描述Product:抽象产品,产品对象的共同父类或共同拥有的接口。
ConcreteProduct:具体产品,具体产品有专门的具体工厂创建,一般一一对应。
Factory:抽象工厂,是工厂方法模式的核心。
ConcreteFactory:具体工厂,是实现抽象工厂接口的具体工厂类,用于创建产品对象。

2、模式实例

一个汽车生产商承接了各种品牌汽车的生产,将其原有的汽车工厂进行分割,为每种品牌的汽车各自设立一个子工厂,宝马汽车工厂专门生产宝马汽车,奔驰汽车厂专门生产奔驰汽车,如果再次承接了其他品牌汽车的生产合作,只需要添加一个对应的工厂即可,无需对原有的工厂进行修改。

2.1 应用场景类图

在这里插入图片描述

2.2 代码实现

(1)Car.java

public interface Car {
	public void run();
}

(2)BMCar.java

public class BMCar implements Car {
	@Override
	public void run() {
		System.out.println("宝马疾驰中...");
	}
}

(3)BCCar.java

public class BCCar implements Car {
	@Override
	public void run() {
		System.out.println("奔驰小汽车飞驰中....");
	}
}

(4)CarFactory.java

public interface CarFactory {
	public Car produceCar();
}

(5)BMFactory.java

public class BMFactory implements CarFactory {

	public Car produceCar() {
		System.out.println("宝马工厂生产宝马汽车中...");
		return new BMCar();
	}

}

(6)BCFactory.java

public class BCFactory implements CarFactory{

	@Override
	public Car produceCar() {
		System.out.println("奔驰汽车厂生产汽车..");
		return new BCCar();
	}
	
}

(7)Client.java

public class Client {
	public static void main(String[] args) {
		Car car;
		CarFactory carFactory;
		carFactory = (CarFactory)XMLUtil.getBean();
		car = carFactory.produceCar();
		car.run();
	}
}

(8)XMLUtil.java

public class XMLUtil {
	public static Object getBean(){
		DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
		
		try {
			//获取doc解析器
			DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
			Document document = dBuilder.parse(new File("./config/factoryMethod.xml"));
			
			//获取doc文本节点
			NodeList nList = document.getElementsByTagName("className");
			Node classNode  = nList.item(0).getFirstChild();
			String carBrand =classNode.getNodeValue();
			
			//通过类名生成实例对象并将其返回
            Class c=Class.forName(carBrand);
	  	    Object obj=c.newInstance();
            return obj;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}

(9)factoryMethod.xml

<config>
	<className>gc.factoryMethod.BCFactory</className>
</config>

3、模式分析

工厂模式是简单工厂模式的进一步抽象和推广,它保持了简单工厂的优点,并克服了缺点,核心的工厂类不再负责所有产品的创建,而是交由具体的子工厂,增加具体产品时,只需要增加相应的具体工厂,而无需修改原有的工厂逻辑。

3.1 优点

能够让工厂自主确定创建何种产品,如何创建对象的细节封装在具体的工厂类中,在系统中加入新产品时,完全符合开闭原则。

3.2 缺点

工厂模式一定程度上增加了系统的抽象性和理解难度,系统中的类的个数会成对增加,增加了系统的复杂度,会带来一部分额外开销。

3.3 适用场景

第一种情况是对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。
第二种情况,只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程这对于使用者来说是透明的。

三、抽象工厂

抽象工厂模式是一种对象创建型模式,用于产品族的构建,抽象工厂模式针对的是多个产品族结构,一个产品族内有多个产品系列。

1、模式结构

在这里插入图片描述AbstractFactory:抽象工厂,是该模式的核心。
ConcreteFactory:具体工厂,用于创建产品的实例,具有有选择合适的产品对象的逻辑。
AbstractProduct:抽象产品,工厂所创建的对象的父类。
ConcreteProduct:具体产品。

2、模式实例

一个汽车生产商承接了各种品牌汽车的生产,又可以生产多种种类的汽车,像公共汽车、小轿车等,相同品牌的汽车构成一个产品族,而相同类型的汽车又构成了一个产品等级结构,使用抽象工厂模式实现该应用。

2.1 应用场景类图

在这里插入图片描述

2.2 代码实现

(1)Car.java

public interface Car {
	public void run();
}

(2)BMCar.java

public class BMCar implements Car{
	@Override
	public void run() {
		System.out.println("宝马轿车行驶中...");
	}
}

(3)BCCar.java

public class BCCar implements Car {
	
	@Override
	public void run() {
		System.out.println("奔驰汽车行驶中...");
	}
}

(4)Bus

public interface Bus {
	public void pull();
}

(5)BMBusjava

public class BMBus implements Bus{
	@Override
	public void pull() {
		System.out.println("宝马大巴拉载乘客中...");
	}
}

(6)BCBus.java

public class BCBus implements Bus{
	@Override
	public void pull() {
		System.out.println("奔驰大巴拉载乘客中....");
	}
}

(7)Factory.java

public interface Factory {
	public Bus produceBus();
	public Car produceCar();
}

(8)BMFactory.java

public class BMFactory implements Factory{
	@Override
	public Bus produceBus() {
		System.out.println("宝马汽车厂生产宝马大巴...");
		return new BMBus();
	}
	@Override
	public Car produceCar() {
		System.out.println("宝马汽车厂生产宝马轿车...");
		return new BMCar();
	}
}

(9)BCFactory.java

public class BCFactory implements Factory{
	@Override
	public Bus produceBus() {
		System.out.println("奔驰汽车厂生产奔驰大巴...");
		return null;
	}
	@Override
	public Car produceCar() {
		System.out.println("奔驰汽车厂生产奔驰轿车...");
		return null;
	}
}

(10)Client.java

public class Client {
	public static void main(String[] args) {
		Bus bus;
		Car car;
		Factory factory = (Factory)XMLUtil.getBean();
		bus = factory.produceBus();
		bus.pull();
		car = factory.produceCar();
		car.run();
	}
}

(11)XMLUtil.java

public class XMLUtil {
	public static Object getBean(){
		
		DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
			Document document = dBuilder.parse(new File("./config/abstractFactory.xml"));
			
			NodeList nList = document.getElementsByTagName("className");
			Node node = nList.item(0).getFirstChild();
			String str = node.getNodeValue().trim();
			
			Object object = Class.forName(str).newInstance();
			return object;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
}

(12)abstractFactory.xml

<config>
	<className>gc.abstractFactory.BMFactory</className>
</config>

3、模式分析

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

3.1 优点

分离了具体的类。客户通过抽象接口操纵实例,产品的类名也在具体工厂的实现中被分离,当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。

3.2 缺点

难以支持新种类的产品。因为抽象工厂接口确定了可以被创建的产品集合,所以难以扩展抽象工厂以生产新种类的产品,增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则。

3.3 适用场景

系统中有多于一个的产品族,但每次只使用其中某一产品族,属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。

参考文献:设计模式(第2版).清华出版社

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值