`
iamxi
  • 浏览: 188694 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

原型工厂模式

阅读更多

    顾名思义就是原型模式和工厂模式的结合。在GOF的书里面,抽象工厂那节中对这个有描述,不过内容很少,所以看的时候也没注意到。

    说个实际的问题:系统需要向用户发送短信,但是根据场景的不同,发送的短信格式也不同,比如重置密码和发送临时验证码的短信格式就有区别,而之前的开发人员使用了策略模式,每个内容都有一个类,现在也不方便去改动这些。但是随需求的增加,发送的场景在不断增加,策略+工厂方法模式的情况下需要去增加更多的if-else,导致扩展困难,也使得调用时候不直观。

    本人自认为自己小脑瓜没有能力想出好办法,只好去翻下书籍,无意中看到了抽象工厂内介绍原型工厂的内容,想着可以借鉴。如果依靠一定规范的传入参数,通过if-else来判断需要使用的算法闲代码忒长,那么不为什么不直接传入算法呢。当然传入算法的类的话太费资源,但是传个Class或Class Name不适问题。

参数就是用枚举,这比String参数好,原因是String可以传入任何字符串,而枚举只能是枚举内的指定值,枚举代码如下:

public enum MessageBuilderEnum {

	RESET_PASSWORD_SMS(ResetPwSmsMsgSendServiceImpl.class),
	RESET_PASSWORD_EMAIL(ResetPwMailMsgSendServiceImpl.class),
	SMS_FEE(SmsFeeMsgSendServiceImpl.class),
	TEMP_CODE_SMS(TempCodeSmsMsgSendServiceImpl.class),
	UNIVERSAL_SMS(BoundMsgSendServiceImpl.class);
	
	private Class<?> builderClass;
	
	MessageBuilderEnum(Class<?> builderClass) {
		this.builderClass = builderClass;
	}
	
	public Class<?> getBuidlerClass() {
		return builderClass;
	}
}

 再看下功能实现的代码

	private static ConcurrentHashMap<String, AbstractMsgSendServiceImpl> messageBuilder = new ConcurrentHashMap<String, AbstractMsgSendServiceImpl>();

	public MessageSendServiceImpl() {
		for (MessageBuilderEnum builderClass : MessageBuilderEnum.values()) {
			try {
				messageBuilder.put(builderClass.getBuidlerClass().getSimpleName(),
						(AbstractMsgSendServiceImpl) builderClass.getBuidlerClass().newInstance());
			} catch (InstantiationException e) {
				logger.error(e.getMessage(), e);
			} catch (IllegalAccessException e) {
				logger.error(e.getMessage(), e);
			}
		}
	}

	@Override
	public String send(ServMessage message, MessageBuilderEnum builderEnum) {
		AbstractMsgSendServiceImpl builder = messageBuilder
				.get(builderEnum.getBuidlerClass().getSimpleName()).clone();
		if (builder != null) {
			return builder.send(message);
		} else {
			return null;
		}
	}

 工厂方法是在构造函数下,在初始化的时候就为枚举下所有的类初始化,然后保存在Map下,用于当作原型。在需要使用的时候再对原型clone一下就是了。

    其实可以在需要使用时候初始化。这里使用原型是听说原型创建新对象比较快,当然本人没仔细测试过,有时间再研究。

    原型工厂的工厂可以是抽象工厂模式,也可以是工厂方法模式

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics