抽象工厂模式(Abstract Factory Pattern)-创建型模式第二篇

解决的问题:

  1. 如何创建一个类,使其能够独立于它所需要的对象
  2. 如何让相关的产品对象能够一同被创建

怎么去解决:

  1. 将一系列具体对象的创建封装在单独的工厂对象里,你需要定义这个工厂的接口,然后实现这个抽象的工厂
  2. 客户端上下文在调用时,通过工厂去创建抽象的产品从而代替直接创建具体的产品对象

定义:

我想抽象工厂的核心定义是提供一个接口,用于创建一组依赖的对象(接口),并且无需指定具体的实现对象

具体的工厂决定了怎样的一系列具体对象会被创建,方法所返回的将是一个抽象的产品接口类型。在运行时上下文中,客户端将依赖于这个抽象的产品接口指针,而不用关心具体的实现提供者是什么。

UML:

实例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AbstractFactory
{
    public interface IButton
    {
    }

    public class FerricButton : IButton
    {
    }

    public class PlasticButton : IButton
    {
    }

    public interface IDisplayPanel
    {
    }

    public class LCDDisplayPanel : IDisplayPanel
    {
    }

    public class LEDDisplayPanel : IDisplayPanel
    {
    }

    public interface IDisplayerFactory
    {
        IButton CreateButton();

        IDisplayPanel CreateDisplayPanel();
    }

    public class HighendDisplayerFactory : IDisplayerFactory
    {
        public IButton CreateButton()
        {
            return new FerricButton();
        }

        public IDisplayPanel CreateDisplayPanel()
        {
            return new LEDDisplayPanel();
        }
    }

    public class LowendDisplayerFactory : IDisplayerFactory
    {
        public IButton CreateButton()
        {
            return new PlasticButton();
        }

        public IDisplayPanel CreateDisplayPanel()
        {
            return new LCDDisplayPanel();
        }
    }

    internal class Program
    {
        private static void Main(string[] args)
        {
            DoWork();
        }

        private static void DoWork()
        {
            IDisplayerFactory displayerFactory;
            while (true)
            {
                Console.WriteLine("Please select the type of displayer you want.");
                Console.WriteLine($"A: LED{Environment.NewLine}B: LCD");
                var inputKey = Console.ReadKey();
                Console.WriteLine();
                switch (inputKey.KeyChar.ToString().ToUpper())
                {
                    case "A":
                        displayerFactory = new HighendDisplayerFactory();
                        Console.WriteLine($"Producing button -- {displayerFactory.CreateButton()}");
                        Console.WriteLine($"Producing display panel -- {displayerFactory.CreateDisplayPanel()}");

                        break;

                    case "B":
                        displayerFactory = new LowendDisplayerFactory();
                        Console.WriteLine($"Producing button -- {displayerFactory.CreateButton()}");
                        Console.WriteLine($"Producing display panel -- {displayerFactory.CreateDisplayPanel()}");
                        break;

                    case "X":
                        return;

                    default:
                        Console.WriteLine("You enter a wrong character and enter 'x' to exit the program");
                        break;
                }
            }
        }
    }

}

输出:

工厂方法模式(Factory Method)-创建型模式第一篇

解决的问题:

  1. 如何创建一个对象,以便子类可以重新定义要实例化的类
  2. 一个类如何将实例化延迟到子类

怎么去解决:

  1. 为创建对象定义单独的操作方法(工厂方法)
  2. 通过调用工厂方法创建对象

定义:

定义用于创建对象的接口,但让子类决定要实例化哪个类。工厂方法允许类延迟实例化它使用的子类。

创建对象通常需要复杂的过程,对象的创建可能导致代码的大量重复,可能需要构成对象无法访问的信息,可能无法提供充分的抽象级别。工厂方法模式通过定义单独的方法去创建对象来处理这些问题,然后子类可以重写以满足未来创建产品的派生类型。 Continue reading "工厂方法模式(Factory Method)-创建型模式第一篇"

《设计模式》系列序——写给未来的自己

老骥伏枥,志在千里;烈士暮年,壮心不已。

起伏间,已然离开软件行业八月有余,斯余生不知是否仍有机遇重返程序员行列,遂作《设计模式》系列以祭之。

在上世纪的经典设计模式著作《设计模式 可复用面向对象软件的基础》中将设计模式进行了3个层面的划分,它们分别是创建型设计模式(Creational patterns)、结构型设计模式(Structural patterns)和行为型设计模式(Behavioral patterns),在本系列中我也将按照这种方式去划分。至于为什么选择设计模式去纪念过去十年的编程岁月,下面是鄙人一些心得体会,与大家分享:

  • 天下武学,万变不离其宗,宗于何处?大道三千,殊途同归,归于何处?所谓模式,是对过往的继承和沉淀,从而得出的一些规律性经验。软件设计模式,也同样是前贤们在处理各种问题时所发现的一些共同的东西,这些是宝贵的经验,这些经验可以用来解决很多看起来似乎很复杂的问题,使系统变得更加健壮、易维护、可扩展。并且有意思的是这些模式不仅仅只体现在软件世界中,也是对现实世界的总结与抽象。比如中介者模式,它就像是对现实世界中中介类问题的一个抽象,你需要货,我有货,你不知道我有货,我不知道你需要货,但中介者知道我有货,也知道你需要货,中介者掌握着资源与手段,它从而肩负起你我之间沟通的能力,而你我或许永远也不知道对方。
  • 软件工程里有一个非常重要的思想叫做面向对象思想,从而扩散出很多理论和方法,比如面向对象分析OOA,面向对象设计OOD,面向对象编程OOP,然而在这世间万物中,面向对象又何止仅仅存在于软件世界,面向对象存在于真实世界的每个角落。在面向对象的世界里,万物皆为对象,对象又由二种东西来组成:属性和行为。比如鸟儿有嘴巴,所以可以吃虫,鸟儿就是对象,嘴巴就是属性,吃虫就是行为。而在设计模式的每一个角落,无不充斥着面向对象思想,没有面向对象,就不会产生设计模式。
  • 设计模式+面向对象,是最易学的,也是最难学的。在写这篇文章的时候,我接触它们也已10年,10年前我说它们就是这样,10年后我还是说它们就是这样,对于我自己来说似乎没有看到自己的成长,我非常希望能够通过书写这一系列文章,从而发现另一个自己。

下面来列一下本系列的文章大纲,总计约23篇设计模式文章,我应当每月会更新一篇,也就总计需要两年时间,希望在那最终完成时,自己还能保持着这份程序员的热情。

创建型模式,共有五篇。

  • 工厂方法 (Factory Method)
  • 抽象工厂 (Abstract Factory)
  • 单例模式 (Singleton Pattern)
  • 建造者模式 (Builder Pattern)
  • 原型模式 (Prototype Pattern)

结构型模式,共有七篇。

  • 桥接模式 (Bridge Pattern)
  • 适配器模式 (Adapter Pattern)
  • 装饰者模式 (Decorator Pattern)
  • 组合模式 (Composite Pattern)
  • 享元模式 (Flyweight Pattern)
  • 外观模式 (Façade Pattern)
  • 代理模式 (Proxy Pattern)

行为型模式,共有十一篇。

  • 模版方法模式(Template Method)
  • 策略模式(Strategy Pattern)
  • 状态模式(State Pattern)
  • 观察者模式(Observer Pattern)
  • 职责链模式(Chain of responsibility)
  • 命令模式(Command Pattern)
  • 中介者模式(Mediator Pattern)
  • 备忘录模式(Memento Pattern)
  • 迭代器模式(Iterator Pattern)
  • 解释器模式(Interpreter Pattern)
  • 访问者模式( Visitor Pattern)

一个自动保存邮件附件的服务

刚到这个工厂工作的时候,这个工厂的一个应用需要将某个发件人发来的邮件中的附件保存在指定的目录下,以便另外一个服务去指定目录下读取这个附件。不过有一个问题是这个应用一直运行的不是很稳定,有的时候它并不能将附件正确保存,并且占用资源较大,后来也引起了一个生产问题。在后来的某个空闲的时刻,便写了这样一个windows service,目前该服务已经稳定运行三月有余,它具有以下功能:

  1. 支持多个邮箱账号
  2. 支持将邮箱中某个文件夹下的附件保存到指定位置
  3. 支持2种收邮件的协议:POP3和IMAP,以及支持SSL传输
  4. 如果某个邮件附件已经保存,会将该邮件标记为已读

由于是windows service,它没有UI界面,直接来看一下它的config file. Continue reading "一个自动保存邮件附件的服务"

B1 Xml Firing 一个极速解决B1iSN daily issue的工具

这是怎样的一个工具?这是一个极速解决你99.99% B1iSN daily issues的工具,会极大的提高你的工作效率。说实话,如果不考虑业务上的限制,这个工具,理论上可以操作任何B1数据。

我们知道在B1iSN的日常问题处理中,作为一个系统集成平台,B1iSN基本上就是将数据从源系统集成到目标系统中。在B1iSN中,通过XML来描述源系统与目标系统的数据转换,下面是一个B1iSN的XML消息实例。 Continue reading "B1 Xml Firing 一个极速解决B1iSN daily issue的工具"

一个梦想

十年以来,长久以来,一直以来,有一个小小的梦想。

想做一件事情,做一件能够让别人记住我的事情(不会考虑恐袭等等等),一件能服务别人,让别人对我表示肯定和赞赏的事情。

但我知道,任何事情如果只有自己一个人去做,如果想成功,会很难很难。特别是对于我这种没什么想法和点子的人。

最近这种想做一件有意义的事的想法异常强烈。

所以我想寻觅一个志同道合、有兴趣一起做一个有意义的微信公众号的朋友。这个微信公众号将长久地开发和维护下去(就像这个博客一样),不为金钱只为兴趣!很显然我没有能力去思考做什么,我只有能力去实现什么,而你将有能力去思考做什么。你出谋划策,我挑灯夜战。

来吧,一起再玩一次!!!联系我!!!niyouzhu#163.com

入职两月纪念文章

刚刚突然想起已经在不知不觉中加入某公司两月整了(2017年5月8日入职,今天是7月7日,现在是17点12分),光阴总是飞逝地很快,不是吗,就像大部分人已经忘记的今天,谁会想起在80年前的今天日本发动了全面侵华战争?不过因为是突然想起,所以来不及酝酿,马上就要下班了,也不应该在上班时间写私人的文章,所以就这样先仓促地起个头吧,待明天周末再好好的回顾一下这两个月的风土人情。

以前没有在厂里工作过,两个月来有一点感悟,工作在厂里和工作在软件公司还是有一些差别:

  1. 首先最显著的一点,信息化的程度,或者换个狭义点的说法,无纸化办公的程度。虽然同样的外商独资企业,但在软件公司里,你能在日常环境下所需要进行地人事、行政事务等(比如请假、报销),基本都是可以通过内部应用系统实现。
  2. 开放环境。在很多软件公司里,尊崇一种开放透明自由的办公氛围和环境,这可能与程序员是一个创造力较强的岗位有关,在大大的场地里,没有玻璃、没有围墙,人与人之间能够互相发现、快速交流。然而,厂里可能更注重私人空间。
  3. 领域知识。在工厂里,你会发现很多人有当前领域的专业知识,但他们可能对IT一窍不通,比如我对面的ITer(负责IT基础设施),就经常遇到别人找他解决Outlook为什么没看到邮件这样的问题。这在软件公司不可想象,在软件公司里应用软件的问题不需要找别人,因为没有人比你自己更了解发生了什么,既然这样,那为什么不自己去解决?
  4. 英语能力。在工厂里,特别是像这种有国外人员常驻的企业里,英语交流(口语)显得格外重要,甚至我一度认为,只要英语口语好,其他都是次要的,有没有专业知识在这里根本不重要。
  5. 系统集成在这种跨国贸易企业显得尤为重要。每天有大量地销售、采购订单在全世界各地产生,如何准确、及时地安排生产和发货似乎决定着企业的竞争力和命运。

好吧,就到这里吧。

File Name Length, 检查文件路径长度的小工具

之所以当时写这个小工具的目的,就是为了解决一些由某些软件生成的文件路径过长(尤其印象深刻的是npm中的资源嵌套),同时由于Windows系统的限制,这些文件可能无法被另外的一些应用所访问,所以就想通过这个小工具来预先检测出那些超过系统限制的文件,然后再逐步解决问题。

Tips: 在Windows系统中,目录名长度要小于248字符(最多247个字符),包括盘符“D:\”(3个字符),目录和目录之间“\”(1个字符,目录和文件之间的“\”不算长度),再加上文件名必须小于260字符(最多259个字符,目录名短,文件名就可以长,目录名长,文件名就要短,总共两者加在一起要小于260个字符)

这个小工具有以下几个功能:

  1. 较高的性能,IO访问一直是软件开发中的一个需要注意的性能瓶颈,为了克服这个问题,在这个小工具中,能够通过自定义线程数来提升访问IO的并发性能(建议可以设置成与CPU的核心数相同,超线程可以*2)
  2. 结果窗口会反馈满足条件的文件路径和当前长度

这个小工具的界面如下:

  1. 主界面
  2. Submit,选择文件夹路径
  3. 点击OK,开始处理

Compactor 批量压缩小工具

在发表这个小工具之前,先说一段小故事。当年在某公司的软件框架组里,每当有新的Release要发布时,总是要将很多Components分别打包压缩上传(每个Component皆是独立的功能组件),实在是烦之又烦,于是乎狠心之下写了这样一个批量打包的工具。它具有以下几个功能:

  1. 支持按文件夹分别压缩打包(每个顶层文件夹会被压缩成一个压缩包,当然也可选择只生成一个压缩包)
  2. 支持两种压缩格式(7z和zip)
  3. 支持三种压缩级别(Normal, Fast 快但压缩比低, High 慢但压缩比高)

下面是操作界面:

  1. 假设现在的目录结构如下,我们需要将b、c两个文件夹分别压缩给不同的客户,并且还需要将b、c两个文件夹压缩在一起作个备份。
  2. 打开小工具主界面(原计划还要再添加几个其它独立功能,所以主界面上当时就设计成一个大大的打开Compactor的按钮)
  3. Compactor的主界面

    1. 需要打包的文件夹目录
    2. 选择需要打包的子目录
    3. 选择打包方式(每个子目录压缩成一个压缩包,还是所有子目录放在一起压缩成一个压缩包)
    4. 选择压缩包文件存放目录
    5. 选择压缩包文件格式(7z, zip)
    6. 选择压缩比
    7. 生成压缩包
  4. 生成压缩包,弹出处理信息
  5. 这是当选择将所有文件夹压缩在一个压缩包中的界面
  6. 最后,文件夹中的结果

DoubleColorBall 双色球号码预测小工具

那一年想发财,于是写了这样一个预测下一期双色球中奖号码的小工具。它具有以下几个功能。

  1. 每天自动同步最新的双色球中球号码到本地(也可以手工触发)
  2. 可以手工添加某一期的中奖号码到历史池,也可修改。
  3. 根据历史池中的所有中奖号码记录,计算下一期的可能中奖号码
  4. 每天自动将下期可能中奖号码发送到指定的邮箱列表(也可手动触发)

下面是工具界面:

  1. 主界面
  2. 查询最近号码,可以查看最近100期的中奖号码
  3. 手动添加某期中奖号码
  4. 修改某期中奖号码
  5. 预测可能中奖号码,可以预测5组。
  6. 修改邮件接收人:

Continue reading "DoubleColorBall 双色球号码预测小工具"