博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python 使用模板模式和工厂模式的混合设计开发各种邮件客户端发送邮件
阅读量:5953 次
发布时间:2019-06-19

本文共 4854 字,大约阅读时间需要 16 分钟。

1、使用模板模式和工厂模式的混合设计开发各种邮件客户端发送邮件。

2、模板模式的目的:能保证快速开发各种邮箱客户端,子类只需要重写模板类邮箱的抽象方法即可。之后再开发任何邮箱就只要加一个类,写3行代码就可以。

工厂模式的目的:能隐藏创建具体对象的细节,只需从工厂类的方法中就能得到各种邮箱客户端。例如被别的模块import时候,只需要import这个工厂类就可以了,不需要去import几十种具体的邮箱客户端。

 

# coding=utf8"""使用模板模式、工厂模式的混合设计,开发各种邮件客户端"""import sysreload(sys)sys.setdefaultencoding('utf8')import reimport unittestfrom abc import ABCMeta, abstractmethodimport smtplibfrom email.mime.text import MIMETextclass MailClient(object):    """一个通用的邮件客户端,作为模板模式的模板类。    该类为抽象类,不可以进行实例化。    _set_smtp方法为抽象方法,子类必须重写这个方法.    """    __metaclass__ = ABCMeta    def __init__(self, msg_from, passwd):        """        :param msg_from: 发件人邮箱地址        :param passwd: 发件人邮箱密码,qq邮箱使用授权码是16个字母,而不是自己的邮箱密码。        """        self._mail_name = None        self._msg_from = msg_from        self._passwd = passwd        self._smtp = None        self._set_smtp()        self.__login()    @abstractmethod    def _set_smtp(self):        pass    def __login(self):        try:            self._smtp.login(self._msg_from, self._passwd)        except smtplib.SMTPAuthenticationError as e:            raise smtplib.SMTPAuthenticationError(535, '{}邮箱登录失败\n'.format(self._mail_name) + e.message)    def send_mail(self, msg_to, subject, content):        """        发送邮件        :param msg_to: 所有收件人的邮箱地址列表,类型为字符串列表,单个接收人也可以用字符串        :param subject :邮件主题        :param content:邮件内容        :return :邮件是否发送成功        :type msg_to:list        :type subject:str        :type content:str        """        msg = MIMEText(content, _charset='utf8')        msg['Subject'] = subject        msg['From'] = self._msg_from        msg['To'] = msg_to        self._smtp.sendmail(self._msg_from, msg_to, msg.as_string())        print '邮件发送成功,发送的邮件主题是: {}   。请去邮箱检查邮件'.format(subject)        return True    def __str__(self):        return '登录帐号为: {0}  的{1}邮箱客户端'.format(self._msg_from, self._mail_name)    def quit(self):        try:   # 如果没登陆成功就关闭连接,会出错,try一下            self._smtp.quit()        except:            pass    def __del__(self):        self.quit()class QQMailClient(MailClient):    def _set_smtp(self):        self._mail_name = 'qq'        self._smtp = smtplib.SMTP_SSL("smtp.qq.com", 465)class Wangyi163MailClient(MailClient):    def _set_smtp(self):        self._mail_name = '163'        self._smtp = smtplib.SMTP_SSL("smtp.163.com", 465)class MailNameException(Exception):    """不支持的邮箱异常类"""    def __init__(self, msg_from):        err = '你设置的邮箱账号是 {}   ,不支持此邮箱'.format(msg_from)        super(MailNameException, self).__init__(err)class MailClientFactory(object):    @staticmethod    def get_mail_client(msg_from, passwd):        """        :param msg_from:发件人邮箱地址        :param passwd:邮箱密码        :return: 具体的邮箱对象        :type msg_from:str        :type passwd:str        :rtype :MailClient        """        if re.match('[0-9a-zA-Z_]+@qq\.com', msg_from):            return QQMailClient(msg_from, passwd)        elif re.match('[0-9a-zA-Z_]+@163\.com', msg_from):            return Wangyi163MailClient(msg_from, passwd)        else:            raise MailNameException(msg_from)class MailTest(unittest.TestCase):    def test_163(self):        """测试163邮箱发送两个邮件"""        wangyi163_mail_client = MailClientFactory.get_mail_client('m13148804506@163.com', '1234567')        print wangyi163_mail_client        wangyi163_mail_client.send_mail('909686716@qq.com', '测试网易163邮箱发送主题1', '测试网易163邮箱发送内容1')        result = wangyi163_mail_client.send_mail('909686716@qq.com', '测试网易163邮箱发送主题2', '测试网易163邮箱发送内容2')        self.assertEqual(result, True, msg='163邮件发送失败')    def test_qq(self):        """测试两个qq号发送邮件"""        qq_123456_client = MailClientFactory.get_mail_client('123456@qq.com', 'ssoodruxniyfxxxx')        print qq_123456_client        qq_789000_client = MailClientFactory.get_mail_client('789000@qq.com', 'ssoodruxniyfxxxx')        print qq_789000_client        result = qq_123456_client.send_mail('m13148804506@163.com', '测试qq邮箱发送主题3', '测试qq邮箱发送内容3')        self.assertEqual(result, True, msg='qq邮件发送失败')        result = qq_789000_client.send_mail('m13148804506@163.com', '测试qq邮箱发送主题4', '测试qq邮箱发送内容4')        self.assertEqual(result, True, msg='qq邮件发送失败')    def test_126(self):        """测试一个不支持的邮箱"""        self.assertRaises(MailNameException, MailClientFactory.get_mail_client, 'm13148804506@126.com', '123456')if __name__ == "__main__":    unittest.main()

 

 

 

3、由此可见,在一个项目中设计模式不是固定的只能用一种,而是可以多种模式混合设计。

1、此项目也可以使用 策略模式来实现,策略类中设置邮箱服务器,Context类中登录和发送邮件,和此文比只有很小的区别。策略模式实现可以参考 

2、由于这个邮箱项目比较简单,这也可以不使用设计模式,不需要增加多个类,只需要一个类就可以实现了。工厂模式的缺点是每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。过度设计这并不是什么好事。

3、也可以用面向过程来实现,缺点是在进行多实例操作时候,小红 小明 小黄登录qq邮箱,需要在类之外设置变量,如果类的属性非常多,比如20个,小红 、小黄 、小明需要在类外设置60个变量来保存这些属性,oop只要3个对象,每个对象有20个属性。oop在状态维护、保存、序列化反序列化上、被别的模块调用更简单、命名空间更清洁、继承这些方面有很大优势。

 

看到有的人是一个函数就实现发邮件,虽然简单,把设置服务、登录、发送邮件、关闭连接放一起了,那样做每发一个邮件都执行连接服务器进行登录发邮件关闭连接这个过程,有一些额外的开销。

 

转载地址:http://xmaxx.baihongyu.com/

你可能感兴趣的文章
urllib模块使用笔记
查看>>
mysql 连接慢的问题(超过了1秒)
查看>>
1297. [SCOI2009]迷路【矩阵乘法】
查看>>
Linux嵌入式GDB调试环境搭建
查看>>
java分析jvm常用指令
查看>>
【Linux】Linux 在线安装yum
查看>>
oracle 管理操作 (转)
查看>>
DEV 等待窗口
查看>>
实验03博客园总结
查看>>
VS2017发布微服务到docker
查看>>
lombok
查看>>
Dev-FAT-UAT-PRO
查看>>
Maven, IntellJ Idea 配置注意点
查看>>
Android开发学习总结(五)——Android应用目录结构分析(转)
查看>>
观察者模式
查看>>
[PHP]PHP rpc框架hprose测试
查看>>
Atom 编辑器系列视频课程
查看>>
C#三种定时器
查看>>
范数 L1 L2
查看>>
协同过滤及大数据处理
查看>>