大话设计模式一:简单工厂模式(simple factory)

本文详细介绍了简单工厂模式的定义、结构图、接口设计原则以及使用场景。通过实例展示了如何通过简单工厂模式降低耦合性和提高系统灵活性。同时讨论了在接口与抽象类的选择上,以及何时考虑使用简单工厂模式。
摘要由CSDN通过智能技术生成

一. 定义:

简单工厂提供一个创建对象实例的功能,而无须关心其具体实现。

简单工厂方法的内部主要实现的功能是:选择合适的实现类来创建实例对象。


二. 结构图:


Api:定义客户端所需要的功能接口

Impl:具体实现Api的实现类,可能会有多个

Factory:工厂,选择合适的实现类来创建Api接口对象

Client:客户端,通过Factory去获取Api接口对象,面向Api接口编程


三. 序列图:



四. 接口回顾:

1. 接口是用来干嘛的?

通常用接口来定义实现类的外观,就相当于一份契约,根据外部应用需要的功能,约定了实现类应该要实现的功能。

2. 接口的思想:封装隔离

3. 使用接口的好处:

只要接口不变,内部实现的变化就不会影响到外部应用,从而使系统更灵活

4. 接口和抽象类的选择:

优先选择接口

在如下情况下选抽象类:既要定义子类的行为,又要为子类提供公共的功能。


五. 简单工厂的例子:

实例1:

定义Operation抽象类,将各种操作解耦为各个类并实现Operation抽象类,这样可以降低了各种具体操作代码耦合性。总体来说,定义一个抽象类,然后若干类继承该抽象类并实现抽象方法,工厂会根据需要生成各种子类对象(多态)。

package simple_factory;

public abstract class Operation {
	private double numberA = 0;
	private double numberB = 0;
	public double getNumberA() {
		return numberA;
	}
	public double getNumberB() {
		return numberB;
	}
	public void setNumberA(double numberA) {
		this.numberA = numberA;
	}
	public void setNumberB(double numberB) {
		this.numberB = numberB;
	}
	public abstract double GetResult() throws Exception;
	
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		Operation oper;
		oper = OperationFactory.createOperation("+");
		oper.setNumberA(1);
		oper.setNumberB(2);
		double result = oper.GetResult();
		System.out.println(result);
	}
}

class OperationAdd extends Operation {
	@Override
	public double GetResult() {
		double result = 0;
		result = this.getNumberA() + this.getNumberB();
		return result;
	}
}

class OperationSub extends Operation {
	@Override
	public double GetResult() {
		double result = 0;
		result = this.getNumberA() - this.getNumberB();
		return result;
	}
}

class OperationMul extends Operation {
	@Override
	public double GetResult() {
		double result = 0;
		result = this.getNumberA() * this.getNumberB();
		return result;
	}
}

class OperationDiv extends Operation {
	@Override
	public double GetResult() throws Exception {
		double result = 0;
		if (this.getNumberB() == 0)
			throw new Exception("除数不能为0");
		result = this.getNumberA() / this.getNumberB();
		return result;
	}
}

class OperationFactory {
	public static Operation createOperation(String operate) {
		Operation oper = null;
		switch (operate)
		{
			case "+":
				oper = new OperationAdd();
				break;
			case "-":
				oper = new OperationSub();
				break;
			case "*":
				oper = new OperationMul();
				break;
			case "/":
				oper = new OperationDiv();
				break;
		}
		return oper;
	}
}

用一个单独的类来做创建实例的过程,这就是工厂。如果现在还需要增加各种复杂运算,比如平方根,只需要增加运算子类继承Operation抽象类,同时修改运算类工厂。

注意:客户端在调用工厂的时候,需要传入参数,这就说明客户端必须知道每个参数的含义,也需要理解每个参数对应的功能处理。这就要求必须在一定程度上,向客户暴露一定的内部实现细节。


实例2:

使用反射加上配置文件,来实现添加新的实现类过后,无需修改代码,就能把这个新的实现类加入应用中。

/**
 * 某个接口(通用的、抽象的、非具体的功能的) 
 */
public interface Api {
	/**
	 * 某个具体的功能方法的定义,用test来演示一下。
	 */
	public void test(String s);
}
/**
 * 对某个接口的一种实现 
 */
public class Impl implements Api{
	
	public void test(String s) {
		System.out.println("Now In Impl. The input s: " + s);
	}
}
/**
 * 工厂类,用来创造Api对象
 */
public class Factory {
	/**
	 * 具体的创造Api的方法,根据配置文件的参数来创建接口
	 */
	public static Api createApi() {
		// 直接读取配置文件来获取需要创建实例的类(使用反射)
		InputStream in = null;
		Properties p = null;
		Api api = null;
		try {
			in = Factory.class.getResourceAsStream("FactoryTest.properties");
			p = new Properties();
			p.load(in);
			// 用反射去创建对象
			api = (Api) Class.forName(p.getProperty("ImplClass")).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return api;
	}
}
配置文件:如果新增了实现类后,修改此配置文件就可以了
ImplClass=cn.javass.dp.simplefactory.myexample.Impl
/**
 * 客户端:测试使用Api接口
 */
public class Client {
	public static void main(String[] args) {
		Api api = Factory.createApi();
		api.test("哈哈,不要紧张,只是个测试而已!");
	}
}

六. 何时使用简单工厂:

1. 如果想要完全封装隔离具体实现,让外部只能通过接口来操作封装体,那么可以选择简单工厂,让客户端通过工厂来获取相应的接口,而无需关心具体实现。

2. 如果想要把对外创建对象的职责集中管理和控制,可以选用简单工厂,把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值