之前项目有个需求,审批流程的时候要根据配置发送信息:发送短信、发送邮件。当时看到这个就想到要用工厂模式,为什么要用工厂模式呢?用工厂模式进行大型项目的开发,可以很好的进行项目并行开发。就是一个程序员和另一个程序员可以同时去书写代码,而不是一个程序员等到另一个程序员写完以后再去书写代码。其中的粘合剂就是接口和配置文件。
通过简单的工厂设计模式可以达到类的 解耦合目的,但是之前的工厂设计模式依然存在问题,那就是在增加一个子类时都需要修改工厂类,这样很麻烦。现在就可以通过反射机制修改工厂类,这样肯定会 非常麻烦。学习完反射机制之后,实际上,此时就可以通过反射机制来改善工厂类,让其在增加子类时可以不用做任何的修改,就能达到功能的扩充,如下:
/** * */ package com.factoryTest; import java.util.Date; import java.util.List; /** * * 描述:邮件短信消息记录 * @author 小当家 * @created 2018年1月11日 */ public class MessageDTO implements java.io.Serializable{ /** * serialVersionUID : long. */ private static final long serialVersionUID = -1985834353259521222L; /** * 消息ID */ private Long messageId; /** * 需要发送短信的手机号码,多个用,隔开 */ private String smsPhone; /** * 需要发送短信的短信内容 */ private String content; /** * 邮件收件人 */ private String mailRecipient; /** * 邮件标题 */ private String mailSubject; /** * 邮件抄送人 */ private String messageCC; /** * 邮件附件ID */ private Long attachId; /** * 消息发送时间 */ private Date sendDate; /** * 消息发送用于什么模块 */ private String module; /** * 发送状态,1:发送成功 0:发送失败 */ private String sendStatus; /** * 发送消息类型:00000000->不发送 、00000001->短信、00000010->邮件、00000100->系统、00000011->短信和邮件以此类推 */ private String sendType; /** * 发送用户 */ private String userCode; /** * 接收用户,多用户可用逗号隔开 */ private String recipientCode; /** * 备注 */ private String note; /** * 附件名称 */ private String attachmentName; /** * 附件地址 */ private String attachPath; private List<Long> attachIds; get set ... }
定义一个发送邮件的接口
/* * */ package com.factoryTest; /** * 描述:发送信息基础类 * @author 小当家 * @created 2018年1月11日 */ public interface SendTypeBase { /** * * 描述 * @author 小当家 * @created 2018年1月11日 */ public void sendMessage(MessageDTO dto); }
写一个发送邮件的类实现接口
/* * */ package com.factoryTest; /** * 描述:发送邮件 * @author 小当家 * @created 2018年1月11日 */ public class SendMail implements SendTypeBase{ @Override public void sendMessage(MessageDTO dto) { System.out.println(dto.getUserCode()+"发送邮件"); } }
实现一个发送短信的类实现接口
/* * */ package com.factoryTest; /** * 描述:发送短信 * @author 小当家 * @created 2018年1月11日 */ public class SendSms implements SendTypeBase{ @Override public void sendMessage(MessageDTO dto) { System.out.println(dto.getUserCode()+"发送短信"); } }
注意:
对比下简单工厂,如:
/* * */ package com.factoryTest; /** * 描述 * @author 小当家 * @created 2018年1月11日 下午4:25:27 */ public class SimpleFactory { public SendTypeBase SendMessage(String type) { if("sms".equals(type)) { return new SendSms(); }else { return new SendMail(); } } }
下面是通过反射实现的工厂类
/* * */ package com.factoryTest; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; /** * 描述:发送信息工厂类 * @author 小当家 * @created 2018年1月11日 */ public class SendMessageFactory { private final static Map<String, String> MESSAGE_MAP = new HashMap<String, String>(); static { //短信 MESSAGE_MAP.put("SMS", "com.factoryTest.SendSms"); //邮件 MESSAGE_MAP.put("EMAIL", "com.factoryTest.SendMail"); } @SuppressWarnings("rawtypes") public static SendTypeBase createClass(String type) throws Exception { if(MESSAGE_MAP.get(type) == null) { throw new Exception("未配置发送信息类型"); } Class classType = Class.forName(MESSAGE_MAP.get(type)); @SuppressWarnings("unchecked") Constructor constructor = classType.getDeclaredConstructor(); return (SendTypeBase) constructor.newInstance(); } }
这里类型其实可以通过配置文件来处理,这样增加一个子类,就不需要改工厂类了。