继上一次经理当面把发邮件、发短信的代码改成工厂模式后,过去了1个月。这一天,小杨找到老罗问:“今天销售问我,用户注册的时候,发邮件的协议是什么?”
“销售问你?他关心这个干吗?”老罗不明白销售并不懂技术,怎么会问这个问题。
“我也不知道,可能是客户问他的吧?他说客户注册后收不到邮件,他们公司只支持POP3协议,猜想可能跟这个有关系”小杨说。
“哦,那我看看代码”,老罗打开了SimpleSenderFactory 这个类,“暂时只支持SMTP协议,那我把POP3加上”。于是老罗把SimpleSenderFactory 改成这样
public class SimpleSenderFactory {
public enum SENDER_TYPE{
MAIL_SMTP,SMS,MAIL_POP3
}
public static Sender product(SENDER_TYPE senderType){
if(senderType == SENDER_TYPE.SMS){
return new SmsSender();
}else if(senderType == SENDER_TYPE.MAIL_SMTP){
MailSender mailSender = new MailSender();
mailSender.config("smtp.gmail.com","true","true","password");
return mailSender;
}else if(senderType == SENDER_TYPE.MAIL_POP3){
MailSender mailSender = new MailSender();
mailSender.config("pop.gmail.com","true","true","password");
return mailSender;
}else{
return null;
}
}
}
同时让小杨也修改了调用的地方。
过了几天,小杨说产品部门说,鉴于上次客户要求加入POP3协议的问题,干脆把IMAP协议也加上吧,老罗把SimpleSenderFactory改了一次。
又过了几天,小杨说:销售上次演示说没收到邮件,让查一下。老罗联系了销售和客户,发现这家客户的邮件服务器是不能加密的,老罗把SimpleSenderFactory改了一次。
这一天,小杨对老罗说:“hi,你那代码能否再加一个发送站内消息的功能?”
“啥,站内信?你以为我这代码是屠龙刀呢,什么都能干,啥玩意都往这里面加,三天两头的改东西,要加你自己加去”,老罗显然是厌倦了,有些不满
“你有气冲销售、产品说去撒啊,我只是写了一个注册功能,后台不都是你写的吗,你那有缺陷,大家好像都以为是我弄的呢”。
“什么叫有缺陷,你给我说清楚”
“有缺陷就是垃圾代码,老子就是说清楚了,怎么了”
“咋的了,又吵起来了,有话好好说!”经理及时制止住了这次纠纷,并且让老罗加上了发站内信的代码,让他改好了马上上线。
第二天,不断有客服反映,很多用户注册收不到短信,老罗忙了一早上,发现是近期频繁修改SimpleSenderFactory这个类,最后一次匆忙上线影响到了发短信的代码。
因为这次事件导致了用户十几个小时内无法注册,成为一次事故,经理把老罗叫到办公室:“你是怎么搞得,客服的投诉电话都打到我这里了”
“小杨老是让我改代码啊,上次又催的急,他自己都没测试发短信的功能”,老罗说。
“都是久经考验的老员工了,怎么思想还这么不成熟,你自己的代码不牢牢控制在自己的手中,出了问题还推卸责任”,经理变了脸色
“我知道了,下次注意,不过现在这情况以后也会出现啊,我每次修改发邮件的功能,或者添加一个新的什么功能,都要修改那个类”,老罗发现经理不好糊弄,转移了话题。
经理重新查看了SimpleSenderFactory,说:“嗯,形势发生了改变,频繁修改MailSender类,但MMSSender基本上不修改,我们应该为每一个类型的Sender子类增加一个工厂类”
首先定义一个工厂接口
public interface SenderFactory {
Sender product();
}
发邮件的工厂类实现工厂接口
public class MailSenderFactory implements SenderFactory{
public Sender product(){
MailSender mailSender = new MailSender();
mailSender.config("smtp.gmail.com","true","true","password");
return mailSender;
}
}
发短信的工厂类实现工厂接口
public class SMSSenderFactory implements SenderFactory{
public Sender product(){
return new SmsSender();
}
}
“这样,我们把发邮件、发短信的实例化隔离开来,以后其中某一个修改不会对其他的产生影响”
调用的时候
MailSenderFactory mailSenderFactory = new MailSenderFactory();
Sender mailSender = mailSenderFactory.product();
mailSender.send("j3@tm.com","j4@tm.com","你好","欢迎");
类图变成了这样
工厂类SenderFactory把创建Sender的工作延迟给具体的子类,比如MailSender,以后修改发邮件的相关代码,不会影响其他的比如发短信的代码。即使新增一个发站内信的功能也不会影响其他的功能。