【设计模式】工厂模式

工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

一、简单工厂模式

由一个工厂对象决定创建一种产品类的实例,即定义一个创建对象的类,由这个类来封装实例化对象的行为。

使用场景:
当需要大量创建某种、某类或某批对象时。


public abstract Operation{
	public abstract getResult(double a,double b);
}

public class OperationFactory{
	
	public static Operation createOperation(String operate){
		Operation op=null;
		switch(operate){
			case "+":
			case "-":
			case "*":
			case "/":
		}
		return op;
	}
	
}

优点:
① 工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,它提供了专门的工厂类用于创建对象。
② 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类 所对应的参数 即可。
③ 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

缺点:
① 由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
② 会增加系统中类的个数,增加了系统的复杂度和理解难度。
③ 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,同样违背了了“开闭原则”;在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
④ 使用了 静态工厂方法 ,造成工厂角色无法形成基于继承的等级结构。


二、工厂方法模式

工厂方法模式: 定义一个用于创建对象的接接口,让子类决定实例化哪一个类。
工厂方法使一个类的实例化延迟到其子类。

结构图:
在这里插入图片描述

工厂方法模式将简单工厂模式中的 case逻辑判断 移到了客户端代码。

在这里插入图片描述

//运算抽象类
public abstract class Operation{
	public abstract double getResult(double a,double b);
}

//工厂接口
public interface IFactory{
	Operation createOperation();
}
//加法工厂
class AddFactory implements IFactory{
	Operation createOperation(){
		return new AddOperation();
	};
}
//减法工厂
class SubFactory implements IFactory{
	Operation createOperation(){
		return new SubOperation();
	};
}

总结:
工厂方法模式就是用 工厂类 来创建 产品类 ,而这个工厂类和产品类均继承自某个抽象类或接口。

优点:
对于功能的扩展不会违背 开放封闭原则 ,复用性较高。


三、抽象工厂模式

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

在这里插入图片描述
优点:
将工厂方法模式的工厂与产品的 一对一 关系变为 一对多 的关系,使得一个工厂能创建一个产品的多个实现类的实例。

缺点:
由于可能封装了大量对象和工厂创建,新加产品需要大批量地修改已定义好的工厂相关的类,因此对于产品和工厂的扩展不太友好。


四、反射+配置文件

为解决工厂方法在修改和扩展功能时的问题:

使用反射机制: 通过传入的 类名(字符串形式) 来判断实例化哪一个子类,而不需要像简单工厂模式一样在switch-case语句中判断;

使用配置文件: 可以不必在原有类中修改反射创建实例时传入的字符串参数,而只需要在配置文件中修改即可,避免了在程序中多处修改的繁琐工作,有效地遵循了开放封闭原则。

public class DataFactory {
	
	private static final String db="DB";
	
	private static final Properties properties=new Properties();
	
	public DataFactory() {
		FileInputStream fin;
		URL url=getClass().getResource("config.propertise");
		try {
			fin = new FileInputStream(new File(url.toURI()));
			properties.load(fin);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (URISyntaxException e) {
			e.printStackTrace();
		}
	}
	
	private static IUser createUser() throws InstantiationException, IllegalAccessException {
		Class<?> clazz = null;
		try {
			clazz = Class.forName(properties.getProperty(db)+"User");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return (IUser) clazz.newInstance();
	}
	
	private static IDepartment createDepartment() throws InstantiationException, IllegalAccessException {
		Class<?> clazz = null;
		try {
			clazz = Class.forName(properties.getProperty(db)+"Department");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return (IDepartment) clazz.newInstance();
	}

总结

三种工厂模式有各自的应用场景,实际应用时能解决问题满足需求即可,可灵活变通,无所谓高级与低级。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nonoas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值