工厂模式的思考

概述

由于java具有封装、继承、多态的特性,我们都会对我们定义的对象进行封装,在使用这些对象之前,我们都会创建对象,也就是我们常用的new XXObject()方式。

当我们是自己封装的对象,我们自己使用的时候是知道怎么创建这个对象的,因为这个对象实现者是我们自己,如下图所示,张三使用自己定义的对象,可以随意创建对象。
在这里插入图片描述
当我们是多人合作的,张三还可能使用李四定义的对象,或者需要引入第三方Jar包中的对象,则变成下面这种方式。
在这里插入图片描述

思考,张三是使用其他人定义的对象或者其他jar包对象,如何创建这些对象呢?这些对象实现细节对张三来说,是一个黑盒,那么我们简单抽象简化一下这个问题,分为接口提供者(创建对象者理解为提供一个接口),使用接口者(使用对象者理解为使用一个接口)
在这里插入图片描述
想获取以上对象,我们是否可以使用某种方式统一起来,或者尽可能让使用者使用起来方便容易一些,接下来我们将讨论一下这个问题。

案例拆分

第一个版本

假设A要提供一些手机对象,需要给B调用,如下图所示。手机对象是独立的对象,对于调用者B来说,需要知道每一个手机对象,才能调用使用在这里插入图片描述
手机对象对应代码

public class HuaWei {
	public String name() {
		return "华为";
	}
}
public class Oppo {
	public String name() {
		return "OPPO";
	}
}
public class XiaoMi {
	public String name() {
		return "小米";
	}
}

调用者B

public class B {
	public static void main(String[] args) {
		// B要先知道有HuaWei这个手机东西,B才能使用
		HuaWei huaWei = new HuaWei();
		huaWei.name();
		// B要先知道有XiaoMi这个手机东西,B才能使用
		XiaoMi xiaoMi = new XiaoMi();
		xiaoMi.name();
	}
}

这种实现方式,给调用者B体验十分不友好,等于B完完全全了解了一遍自己要使用的对象,而这些对象实现本该由A来完成。

抽象 + 简单工厂方法

A对手机对象进行抽象,提供一个抽象接口给B使用,避免B直接使用手机对象。如果只是进行抽象,能改善吗?如下图所示。
在这里插入图片描述
手机对象对应代码

public interface Phone {
	String name();
}
public class HuaWei implements Phone {
	public String name() {
		return "华为";
	}
}
public class Oppo implements Phone {
	public String name() {
		return "OPPO";
	}
}
public class XiaoMi implements Phone {
	public String name() {
		return "小米";
	}
}

调用者B

public class B {
	public static void main(String[] args) {
		// B要先知道有HuaWei这个手机东西,B才能使用
		Phone huaWei = new HuaWei();
		huaWei.name();
		// B要先知道有XiaoMi这个手机东西,B才能使用
		Phone xiaoMi = new XiaoMi();
		xiaoMi.name();
	}
}

我们发现这种实现方式,给调用者B来讲,情况和第一个版本没什么区别,尽管代码抽象为Phone huaWei = new HuaWei();,对于B调用者来说,new HuaWei();步骤也是要了解有HuaWei这个对象才能使用,实际上没有任何改善,还增加的代码的复杂度。

继续优化。A提供简单工厂方法实现

public class PhoneSimpleFcatory {
	public static Phone getPhone(String type) {
		if ("O".equals(type)) {
			return new Oppo();
		} else if ("H".equals(type)) {
			return new HuaWei();
		} else if ("X".equals(type)) {
			return new XiaoMi();
		}
		return null;
	}
}

A向B提供简单工厂方法使用API

手机类型参数入参对应手机
H华为
OOPPO
X小米

调用者B

public class B {
	public static void main(String[] args) {
		// B根据API获取HuaWei手机
		Phone huaWei = PhoneSimpleFcatory.getPhone("H");
		huaWei.name();
		// B根据API获取XiaoMi手机
		Phone xiaoMi = PhoneSimpleFcatory.getPhone("X");
		xiaoMi.name();
	}
}

由于A向B提供了一份API使用,B不用再关心是否有HuaWei、XiaoMi等手机对象,只需要传入参数就可以获取到自己想要的对象,对调用者使用友好。调用关系将变成下面这种调用关系。

在这里插入图片描述

大规模对象演进,工厂方法

随着手机对象不断增多,原来的方式API管理的对象越来越大,对于调用者来说,对于对象提供者A与对象使用者B成本都越来大,需要对设计进行二次抽象
在这里插入图片描述
引入工厂方法,引入分层思想,将结构分类,类似于工程模块分解。单从HuaWeiFactory来说,这个小模块是抽象 + 简单工厂方法,对于所有手机来说,这是二次抽象

在这里插入图片描述

HuaWeiFactory部分代码

public class HuaWei implements Phone {
	public String name() {
		return "华为";
	}
}
public class HuaWei2 implements Phone {
	public String name() {
		return "华为2";
	}
}
public class HuaWei3 implements Phone {
	public String name() {
		return "华为3";
	}
}
public interface Factory {
	Phone getPhone(String type);
}
public class HuaWeiFactory implements Factory{
	@Override
	public Phone getPhone(String type) {
		if ("1".equals(type)) {
			return new HuaWei();
		} else if ("2".equals(type)) {
			return new HuaWei2();
		} else if ("3".equals(type)) {
			return new HuaWei3();
		}
		return null;
	}
}

调用者B

public class B {
	public static void main(String[] args) {
		Factory Factory = new HuaWeiFactory();
		// B根据API获取HuaWei手机
		Phone huaWei = Factory.getPhone("1");
		huaWei.name();
		// B根据API获取HuaWei2手机
		Phone xiaoMi = Factory.getPhone("2");
		xiaoMi.name();
	}
}

通过模块分解,我们将大规模拆分为小规模,这也是我们做工程的思想

是否能不提供文档API

上述步骤中A向B提供简单工厂方法使用API

手机类型参数入参对应手机
H华为
OOPPO
X小米

需要A人工维护这份文档,那么我们能否不提供API,B也能知道,答案是肯定的,因为对于java中的接口来说,接口就是API,那么我们继续优化,继续抽象分层。在这里插入图片描述
那我门的逻辑将变成以下关系,
在这里插入图片描述

具体代码表现,这里不再实现,给出B调用代码

public class B {
	public static void main(String[] args) {
		// 手机服务商
		PhoneProvider provider = new PhoneProvider();
		// 手机工厂
		HuaWeiFactory huaWeiFactory = provider.getHuaWeiFactory();
		// B获取HuaWei手机
		Phone huaWei = huaWeiFactory.getHuaWei();
		huaWei.name();
		// B获取HuaWei2手机
		Phone huaWei2 = huaWeiFactory.getHuaWei2();
		huaWei2.name();
		// 手机工厂
		XiaoMiFactory xiaoMiFactory = provider.getXiaoMiFactory();
		// B获取HuaWei手机
		Phone xiaoMi = xiaoMiFactory.getXiaoMi();
		xiaoMi.name();
	}
}

最终形式,接口即API,A只向B提供PhoneProvider,B根据接口方法自动选择自己想要的对象

Spring 注入思想

待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值