工厂模式提升之路(无痴迷,不成功)

  上一篇中聊了工厂模式的进化过程,了解了从简单工厂到工厂方法再到抽象工厂的全过程以及进化原因。进化到抽象工厂确实解决耦合等问题,但是会导致我们扩展时需要修改多个工厂相关类。很不优雅,不符合我们懒人的气质。

  没了解过工厂模式进化之路的客官请先移步: 工厂模式进化之路

  接下来我们聊聊怎么样才能既保留抽象工厂的优点,又解决它的缺点。提前声明一下:工厂模式已经讲完了,下面的不是某一种工厂了,属于工厂的运用优化。如果进化之路讲的是某个技能的介绍,那这篇文章讲的就是连招的使用

首先我们在多个方面总结对比一下三个工厂模式:

  • 在实现方式上:简单工厂抽象了产品类,工厂方法抽象了工厂类,抽象工厂是让抽象的工厂中有了多个分类创建方法。
  • 在功能上:简单工厂实现了对象创建与松耦合,工厂方法使工厂更加有条理并且符合了“开闭原则”,抽象工厂对工厂进行了分类,合并和整理。

注:本文代码中类的关系继续沿用上一篇文章
工厂模式进化之路

抽象工厂与简单工厂相结合(1、3连招)

使用简单工厂解决抽象工厂的问题:”增加时需要改的地方多的问题“

抽象工厂与简单工厂结合的代码:

public class KeyboardFactory{
	private static final String name = "XM"
	//private static final String name = "HW"
	...其他品牌的名字。
	public Keyboard createKeyboard(){
		Keyboard = null;
		switch(name){
			case "XM":
				Keyboard = new XMkeyboard();
				break;
			case "HW":
				Keyboard = new HWkeyboard();
				break;
			...
		}
	}
	//MechanicalKeyboard是继承自Keyboard的。
	public MechanicalKeyboard createMechanicalKeyboard(){
		MechanicalKeyboard = null;
		switch(name){
			case "XM":
				MechanicalKeyboard = new XMMechanicalKeyboard();
				break;
			case "HW":
				MechanicalKeyboard = new HWMechanicalKeyboard();
				break;
			...
		}
	}
}

客户端使用:

class Xiaomi{
	...
	private void useKeyboard(){
		...
		KeyboardFactory factory = new KeyboardFactory();
		Keyboard 键盘实例 = factory.createKeyboard();
		Keyboard 机械键盘实例 = factory.createMechanicalKeyboard();
		...
	}
	...
}

  通过上面的连招,没有了简单工厂管理无序的问题,也解决了抽象工厂扩展时需要增加很多类的问题。而且也不需要像简单工厂一样需要传递参数了,因为参数在类中写死了。
  但是我们发现,在这种结合方式中,如果进行扩展会和简单工厂一样违反“开闭原则”。所以我们想一下如何才能去除switch case语句让他可以自己去找需要实例化的类。

反射+抽象工厂(身法+大招)

  反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为反射机制。
  简单一点来说:我可以用一个字符串通过反射获取任意一个类。
改造代码:

public class KeyboardFactory{
	private static final String route = "某一个种类的实体类所在的包路径";
	private static final String name = "XM";
	//private static final String name = "HW"
	...其他品牌的名字。
	public Keyboard createKeyboard(){
		// 通过反射机制,获取Class,通过Class来实例化对象
        Class c = Class.forName(route+"."+name+"keyboard");
        // 重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
        return c.newInstance();
	}
	//MechanicalKeyboard是继承自Keyboard的。
	public MechanicalKeyboard createMechanicalKeyboard(){
		// 通过反射机制,获取Class,通过Class来实例化对象
        Class c = Class.forName(route+"."+name+"MechanicalKeyboard");
        // 重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
        return c.newInstance();
	}
}

通过上面的结合方式我们就可以完全去除switch case 语句了,还使代码更加简洁了。而且,name是可以作为参数进行传递的,这样我们之后要进行任何扩展都只改name的值就可以了。
此时还有一个问题没有解决:name的值哪里来?难道只能写死吗?写死也太不灵活了对吧

配置文件、数据库(辅助加成)

为了灵活 方式有多种:

  • 配置文件
  • 数据库

等任何存储性组件,个人更倾向于数据库。
我们只要让程序可以在某个地方读取到name的值就可以

至此工厂模式的讨论结束。工厂模式实现了比较完善的功能闭环。基本的问题都已经解决,期待大家可以在未来通过工厂模式使自己的代码更上一层楼。希望我的一点总结可以帮助到大家。
期待大家点赞加关注

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值