戏说设计模式-工厂模式

来源:互联网 发布:自制选择题软件 编辑:程序博客网 时间:2024/05/17 07:49

  今天一大早,经理就把老罗和小杨召集起来,说:今天的主要任务是在我们的平台中加上用户注册的功能。用户填写基本资料,其中包含手机号,要确保是一个真实的手机,所以要用验证码,注册成功后,平台发一封邮件到他的邮箱里面。老罗,你负责调研、编写手机验证码,发邮件的部分。小杨,你负责界面和业务流程部分。说完,大家就各自开工了。

下午的时候,老罗对小杨说:发邮件发短信的功能,我都帮你写好了,分别在utils.MailSender和utils.SMSSender里面,已经push到gitlab上了。

“知道了,我一会儿调一下试试。”小杨自己的部分还没有做完,头也不抬的回应着。

过了一会儿,小杨对老罗喊了一声:“老罗,发邮件报错了,空指针,我发给你报错信息。“

“空指针?我自己测试过的啊!”

老罗,根据报错信息中提示的错误行数找到相应的代码研究起来,然后又运行了一遍他的测试程序,发现并没有错,然后就到小杨座位上想看看是怎么回事。他看到小样的代码,下意识地喊了一句:“你调错了,少写一行代码,我说怎么我那边不报错。”随后,老罗打开自己的代码,还跟小杨解释说

这是发送工具接口,就一个方法

public interface Sender {    void send(String from,String to,String subject,String content);}
这是发短信工具的实现类,SMSSender,我用的淘宝的工具类

import com.taobao.api.ApiException;import com.taobao.api.DefaultTaobaoClient;import com.taobao.api.TaobaoClient;import com.taobao.api.request.AlibabaAliqinFcSmsNumSendRequest;import com.taobao.api.response.AlibabaAliqinFcSmsNumSendResponse;public class SmsSender implements Sender{    public static final String SMS_SEND_URL = "http://gw.api.taobao.com/router/rest";    public static final String APPKEY = "xxxx";    public static final String SECRET = "xxxxxxxx";    public static final String SIGN = "测试";    @Override    public void send(String from, String to, String subject, String content){        TaobaoClient client = new DefaultTaobaoClient(SMS_SEND_URL, APPKEY, SECRET);        AlibabaAliqinFcSmsNumSendRequest req = new AlibabaAliqinFcSmsNumSendRequest();        //req.setExtend("123456");        req.setSmsType("normal");        req.setSmsFreeSignName(SIGN);        req.setSmsParamString(content);        req.setRecNum(to);        req.setSmsTemplateCode("10010");        AlibabaAliqinFcSmsNumSendResponse rsp = null;        try {            rsp = client.execute(req);        } catch (ApiException e) {            e.printStackTrace();        }    }}


这是邮件工具的实现类,MailSender

package factory;import javax.mail.*;import javax.mail.internet.AddressException;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeMessage;import javax.mail.Message.RecipientType;import java.util.Calendar;import java.util.Properties;/** * Created by user on 2016/8/18. */public class MailSender implements Sender {    Properties props = new Properties();    public Properties config(String smtpHost,String starttls,String auth,String password){        props.put("mail.smtp.host", smtpHost);        props.put("mail.smtp.starttls.enable",starttls);//使用 STARTTLS安全连接        props.put("mail.smtp.auth", auth);// 使用验证        props.put("mail.smtp.password", auth);// 密码        return props;    }    @Override    public void send(String from,String to,String subject,String content) {        Session mailSession = Session.getInstance(props,new MyAuthenticator(from,props.getProperty("mail.smtp.password")));        Transport transport = null;        try {            transport = mailSession.getTransport("smtp");        } catch (NoSuchProviderException e) {            e.printStackTrace();        }        InternetAddress fromAddress = null;        InternetAddress toAddress = null;        try {            fromAddress = new InternetAddress(from);            toAddress = new InternetAddress(to);        } catch (AddressException e) {            e.printStackTrace();        }        MimeMessage message = new MimeMessage(mailSession);        try {            message.setFrom(fromAddress);            message.addRecipient(RecipientType.TO, toAddress);            message.setSentDate(Calendar.getInstance().getTime());            message.setSubject(subject);            message.setContent(content, "text/html;charset=gb2312");            transport.connect(props.getProperty("mail.smtp.host"),from, props.getProperty("mail.smtp.password"));            transport.send(message, message.getRecipients(RecipientType.TO));        } catch (MessagingException e) {            e.printStackTrace();        }    }    class MyAuthenticator extends Authenticator {        String userName="";        String password="";        public MyAuthenticator(){        }        public MyAuthenticator(String userName,String password){            this.userName=userName;            this.password=password;        }        protected PasswordAuthentication getPasswordAuthentication(){            return new PasswordAuthentication(userName, password);        }    }}
“你看看你是怎么调用的”

MailSender mailSender = new MailSender();mailSender.send("j1@tm.com","j2@tm.com","谢谢","谢谢注册");
“调用send之前应该要调用一下config方法,输入一些配置信息啊”。老罗埋怨小杨道。

"我哪里知道要先调用一下config方法"小杨有些委屈。

老罗突然意识到,小杨并没有看过自己的代码,不过还是说了一句:“调之前你看一下嘛”

“我那边功能还没做完呢。”小杨听到这句话,感到一股怒火油然而生,但还是压住了怒火,因为他感到老罗在推卸责任。

“就算是你不知道我怎么实现的,报错后也可以调试一下吧,这么简单一个代码,调试一下就明白了啊,没见过这么笨的”。

“你代码报错了还让我调试”。

“我那边没报错,到你这就报错了,你还不承认是你的问题?”。老罗非常确信的认为这个问题是小杨的问题

“你写那垃圾代码,我根本不稀罕看,说我笨?我用过spark,信不信老子弄死你”,小杨完全不想跟老罗纠缠了,语调上扬。

老罗被小杨的话震惊了,撒腿就跑到经理办公室,推开门喊道:“经理,小杨要弄死我......”。

经理看到狼狈的老罗,被突如其来的场景吓了一跳,手忙脚乱的关掉直播软件,同时问到:“什...什么?”老罗把刚才发生的一幕告诉了经理。经理跟着老罗来到了小杨的座位旁,看了看他们俩的代码,说到:“小杨,大家都是同事,干嘛要说弄死谁的呢,有话好好说嘛,老罗,你也是,都是老员工了,你任务做的快,也要好好的思考一下,能否优化呢,怎么总是不注意呢!你代码本身没什么问题,但是你忽略了一件事情,就是一个项目是团队协作完成的,要尽量的站在队友的角度看问题嘛,你调研完成了代码,但是别人没有经历过你代码完成的过程,他们并没有思考过你曾经思考过的问题,有很多细节他们是不知道的,你认为这样调用代码是理所当然的,但别人不一定是这样想的啊”

"那我总不能每次写完自己的代码,都要跟别人从头到尾讲一遍吧,我想讲,他们也不一定想听啊,就算是他们想听,也不一定能听懂啊,你说是不是",老罗看着小杨说。

小杨正想反击,经理按住他说:“呵呵,别人确实不想知道你代码的细节,不过你也不要把责任推卸给别人,你的代码稍微改一下就不会发生刚才的扯皮事件,你看好,我来改一下”。说着,经理坐在了座位上亲自动手改了起来,边改边解释。

首先,我们把MailSender改造一下,让他的配置用的props可以从外部类访问

package factory;import javax.mail.*;import javax.mail.internet.AddressException;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeMessage;import javax.mail.Message.RecipientType;import java.util.Calendar;import java.util.Properties;/** * Created by user on 2016/8/18. */public class MailSender implements Sender {    private Properties props = null;    public Properties getProps() {        return props;    }    public void config(String smtpHost, String starttls, String auth, String password){        props.put("mail.smtp.host", smtpHost);        props.put("mail.smtp.starttls.enable",starttls);//使用 STARTTLS安全连接        props.put("mail.smtp.auth", auth);// 使用验证        props.put("mail.smtp.password", auth);// 密码    }    @Override    public void send(String from,String to,String subject,String content) {        if(props == null){            config("smtp.gmail.com","true","true","admin_password");        }        Session mailSession = Session.getInstance(props,new MyAuthenticator(from,props.getProperty("mail.smtp.password")));        Transport transport = null;        try {            transport = mailSession.getTransport("smtp");        } catch (NoSuchProviderException e) {            e.printStackTrace();        }        InternetAddress fromAddress = null;        InternetAddress toAddress = null;        try {            fromAddress = new InternetAddress(from);            toAddress = new InternetAddress(to);        } catch (AddressException e) {            e.printStackTrace();        }        MimeMessage message = new MimeMessage(mailSession);        try {            message.setFrom(fromAddress);            message.addRecipient(RecipientType.TO, toAddress);            message.setSentDate(Calendar.getInstance().getTime());            message.setSubject(subject);            message.setContent(content, "text/html;charset=gb2312");            transport.connect(props.getProperty("mail.smtp.host"),from, props.getProperty("mail.smtp.password"));            transport.send(message, message.getRecipients(RecipientType.TO));        } catch (MessagingException e) {            e.printStackTrace();        }    }    class MyAuthenticator extends Authenticator {        String userName="";        String password="";        public MyAuthenticator(){        }        public MyAuthenticator(String userName,String password){            this.userName=userName;            this.password=password;        }        protected PasswordAuthentication getPasswordAuthentication(){            return new PasswordAuthentication(userName, password);        }    }}


我们把实例化的工作放到另外一个类中,并且提供一个方法根据参数进行实例化。

public class SimpleSenderFactory {    public enum SENDER_TYPE{        MAIL,SMS    }    public static Sender product(SENDER_TYPE senderType){        if(senderType == SENDER_TYPE.SMS){            return new SmsSender();        }else if(senderType == SENDER_TYPE.MAIL){            MailSender mailSender = new MailSender();            mailSender.config("smtp.gmail.com","true","true","password");            return mailSender;        }else{            return null;        }    }}

这样,我们把实例化的职责从使用方拿了回来。接下来看如何使用

Sender sender = SimpleSenderFactory.product(SimpleSenderFactory.SENDER_TYPE.MAIL);sender.send("j3@tm.com","j4@tm.com","你好","欢迎");
虽然,还是要对使用方说明SimpleSenderFactory的使用方式,但无疑他屏蔽了发邮件的实现细节。SimpleSenderFactory是一个工厂类,他负责产生Sender产品,发邮件工具类和发短信工具类都是他的具体产品,SimpleSenderFactory把这些产品的实例化方法都管理起来,不过呢,将来新增一个Sender类型的产品,就需要修改SimpleSenderFactory,这也是他的一个缺点。










1 0
原创粉丝点击