戏说设计模式-工厂模式

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

下午的时候,老罗对小杨说:发邮件发短信的功能,我都帮你写好了,分别在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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值