设计模式之工厂家族

《冒号课堂编程范式与OOP思想》 13.1 创建模式笔记

工厂家族

构造器的弊端:名字必须与类名一致,缺乏表现力;每次调用都会创建新对象;无法多态,new 必须使用具体类型,没法使用抽象的超类型。

抽象工厂模式:
1. 把静态工厂拆分成了一个接口和若干个实现类;
2. 把工厂方法模式中的主题类中的抽象工厂方法提炼为一个接口,用对象合成取代了类继承。

代码说明示例

1. 静态工厂模式:

public class StaticFactory {
    public enum Type {
        AWT, SWING
    };

    public static Container createFrame(Type type, String title) {
        switch (type) {
            case AWT:
                return new Frame(title);
            case SWING:
                return new JFrame(title);
            default:
                return null;
        }
    }

    public static Component createLabel(Type type, String text) {
        switch (type) {
            case AWT:
                return new Label(text);
            case SWING:
                return new JLabel(text);
            default:
                return null;
        }
    }
}

// 使用静态公共方法的类
class LoginForm {
    public Container createLoginWindow() {
        // 使用前要指定具体的类型
        StaticFactory.Type type = StaticFactory.Type.AWT;
        Container frame = StaticFactory.createFrame(type, "标题");
        Component label = StaticFactory.createLabel(type, "文本");
        // 组装组件
        return null;
    }
}

每个创建对象的方法都通过参数来指定要创建的具体对象类型,调用方必须指定具体的类型。

继续阅读

《冒号课堂:编程范式与OOP思想》之编程范式笔记

《冒号课堂:编程范式与OOP思想》 写得非常有趣,对了解编程语言的发展、不同的编程范式有非常大的帮助。

1.4 编程范式

编程范式是计算机编程中的基本风格和典范模式,引导人们带着其特有的倾向和思路去分析和解决问题。

抽象的编程范式必须通过具体的编程语言来体现。范式的世界观体现在语言的核心概念中,范式的方法论体现在其表达机制中。一种语言的语法和风格与其所支持的编程范式密切相关。

1.5 开发技术

在宏观上选取一些框架以控制整体的结构和流程,在微观上利用库和工具包来解决具体的细节问题。

  • 框架:使设计者在特定领域的整体设计上不必重新发明轮子,是一种设计重用。利用控制反转机制实现对模块的统一调度,给程序员带来约束。

  • 库/工具包:使开发者摆脱底层编码,专注特定问题和业务逻辑;是代码重用。为程序员带来自由。

  • 设计模式(design pattern)和架构(architecture)不是软件产品,而是软件思想。设计模式是战术思想,架构是战略思想。

  • 设计模式:是针对某些经常出现的问题而提出的行之有效的设计解决方案,侧重思想重用,因此比框架更抽象、更普适,但多局限于局部解决方案,没有框架的整体性。

  • 惯用法(idiom):也是针对常发问题的解决方案,偏重实现而非设计,与实现语言密切相关,是一种更底层更具体的编程技巧。

  • 架构:一般指一个软件系统的最高层次的整体结构和规划,一个架构可能包含多个框架,而一个框架可能包含多个设计模式。

继续阅读

流水账式开发 VS. 有重点的开发

流水账日记

小时候写日记很可能出现这样的:

今天早上我7点钟起床,起床后刷牙、洗脸,然后吃早餐,吃了早餐去上学。去到学校,第一节是语文课,语文课下课后跟小明一起玩,然后上数学课,数学课下课后也是跟小明一起玩,然后上体育课,上完体育课我们吃午餐、午睡。。。。(中间省略一千字)下午4点半下课后我回家,回到家我先吃了个雪糕,然后开始写语文作业,写完语文作业写数学作业。。。(再次省略一千字)。。。今天我度过了快乐、充实的一天。

这样的日记如白开水般平淡无味地描述了一天的经过,读完之后让人一脸茫然,不知重点是什么、要关注什么。

一个开发任务

现在有个开发任务:从数据库的 t_smsinfo 表取从未发送或发送失败3次以下的短信进行发送。如果发送成功了就标记为成功不再再次发送;如果发送失败了就记录失败的原因、增加失败次数,失败次数达到3次的就不再重试。

t_smsinfo 表有下列字段:

  • id:唯一标识符;
  • mobile:目标手机号;
  • text:短信内容;
  • send_by_comp:发送短信的公司,目标是支持以多家公司的名义发送;
  • msg_type:消息类型,因为有不同的业务场景,希望做区分;
  • status 表示发送状态,它的取值为: ‘W’ 表示未发送,’F’ 表示发送失败,’G’ 表示发送中。
  • sendout_time:最近一次发送时间。
  • fail_reason:最近一次发送失败的原因,希望分析失败原因;
  • fail_times 表示失败的次数,默认是 0 。

继续阅读

TCP/IP 协议详解 第4章 ARP:地址解析协议

ARP:地址解析协议,是一个基础协议,它的允许对于应用程序和系统管理员一般是透明的。

引言

当一台主机把以太网数据帧发送到位于同一局域网上的另一台主机时,是根据48bit 的以太网地址来确定目的接口的。设备驱动程序从不检查IP数据报中的目的IP地址。

地址解析为 32bit 的IP地址和数据链路层使用的任何类型的地址 提供映射。ARP为IP地址到对应的硬件地址之间提供动态映射。

ARP在TCP/IP协议族中的位置

apr-in-tcpip

ARP背后的一个基本概念是网络接口有一个硬件地址。在硬件层次上进行的数据帧交换必须有正确的接口地址。知道主机的IP地址并不能让内核发送一帧数据给主机,内核(如以太网驱动程序)必须知道目的端的硬件地址才能发送数据。

继续阅读

TCP/IP 协议详解 第3章 IP:网际协议

IP是TCP/IP协议族中最为核心的协议。所有的TCP、UDP、ICMP以及IGMP数据都以IP数据报格式传输。IP提供了不可靠、无连接的数据报传送服务。

不可靠(unreliable)的意思是它不能保证IP数据报能成功地到达目的地。IP仅提供最好的传输服务。任何可靠性要求必须由上层来提供。

无连接(connectionless)是指IP并不维护任何关于后续数据报的状态信息。每个数据报的处理是相互独立的,这也就是说IP数据报可以不按发送顺序接收。

继续阅读

TCP/IP 协议详解 第2章 链路层

在TCP/IP协议族中,链路层主要有三个目的:

  1. 为IP模块发送和接收IP数据报;
  2. 为ARP模块发送ARP请求和接收ARP应答;
  3. 为RARP发送RARP请求和接收RARP应答。

以太网和IEEE 802封装

以太网这个术语一般是指DEC、Intel、Xeror公司在1982年联合发布的一个标准,它是当今TCP/IP采用的主要的局域网技术,以太网IP数据报的封装在RFC894中定义,地址是48bit。

IEEE 802 是IEEE(电子电气工程师协会)802委员会公布的一个稍有不同的标准集,其中802.3针对整个CSMA/CD网络,802.4针对令牌总线网络,802.5针对令牌环网络。

最常用的封装格式是RFC894。

IEEE 802.2/802.3(RFC-1042)和以太网封装格式(RFC-894) (方框下的数字表示占用的字节数):
ieee802和以太网帧封装格式

继续阅读

TCP/IP 协议详解 第1章 概述

引言

TCP/IP起源于60年代美国政府资助的一个分组交换网络研究项目。

下面的说明来自 维基百科:

  • 分组交换:在计算机网络和通讯中是一种相对于电路交换的通信范例,分组(又称消息、或消息碎片)在节点间单独路由,不需要在传输前先建立通信路径。
  • 电路交换:要求必须首先在通信双方之间建立连接通道。在连接建立成功之后,双方的通信活动才能开始。通信双方需要传递的信息都是通过已经建立好的连接来进行传递的,而且这个连接也将一直被维持到双方的通信结束。在某次通信活动的整个过程中,这个连接将始终占用着连接建立开始时,通信系统分配给它的资源(通道、带宽、时隙、码字等等),这也体现了电路交换区别于分组交换的本质特征。

分层

网络协议通常分为不同层次进行开发,每一层分别负责不同的通信功能。一个协议族,比如TCP/IP,是一组不同层次上的多个系统的组合。

继续阅读

TCP/IP 协议详解 第22、23章 TCP的定时器

第22章 TCP的坚持定时器

TCP通过让接收方指明希望从发送方接收的数据字节数(即窗口大小)来进行流量控制。如果窗口大小为0将有效阻止发送方传送数据,直到窗口变为非0为止。

ACK的传输不可靠,TCP不对ACK报文段进行确认,TCP只确认那些包含有数据的ACK报文段。

为了防止 “接收方等待接收数据(因为它已经向发送方通告了一个非0窗口),而发送方在等待允许它继续发送数据的窗口更新” 这种死锁发生,发送方使用一个坚持定时器(persist timer)来周期性地向接收方查询,以便发现窗口是否已增大。这些从发送方发出的报文段称为窗口探查(window probe)。

坚持状态与重传超时之间的一个不同的特点就是TCP从不放弃发送窗口探查,这个过程将持续到 或者窗口被打开,或者应用程序使用的连接被终止。

糊涂窗口综合症

糊涂窗口综合症(SWS,Silly Window Syndrome)发生时会出现:少量的数据将通过连接进行交换,而不是满长度的报文段。

该现象可发生在两端中的任何一端:接收方可以通告一个小的窗口(而不是一直等到有大的窗口时才通告),而发送方也可以发送少量的数据(而不是等待其他的数据以便发送一个大的报文段)。可以在任何一端采取措施避免出现糊涂窗口综合症的现象。

  • 接收方不通告小窗口。通常的算法是接收方不通告一个比当前窗口大的窗口(可以为0),除非窗口可以增加一个报文段大小(也就是将要接收的MSS)或者可以增加接收方缓存空间的一半,不论实际有多少。

第23章 TCP的保活定时器

保活定时器不是TCP规范的一部分。

保活功能主要是为服务器应用程序提供,试图在服务器端检测客户端已消失的半开放的连接。

使用保活选项的一端称为服务器,另一端则为客户端,可以两端都使用。

如果一个给定连接在两个小时内没有任何动作,则服务器向客户发送一个探查报文段。客户主机必须处于以下4个状态之一:

  1. 客户主机依然正常运行,并从服务器可达。客户的TCP响应正常,而服务器也知道对方是正常工作的。服务器在两小时以后将保活定时器复位。如果在两个小时定时器到时间之前有应用程序的通信量通过此连接,则定时器在交换数据后的未来2小时再复位。
  2. 客户主机已经崩溃,并且关闭或者正在重新启动。在任何一种情况下,客户的TCP都没有响应。服务器将不能够收到对探查的响应,并在75秒后超时。服务器总共发送10个这样的探查,每个间隔75秒。如果服务器没有收到一个响应,它就认为客户主机已经关闭并终止连接。
  3. 客户主机崩溃并已经重新启动。这时服务器将收到一个对其保活探查的响应,但是这个响应是一个复位,使得服务器终止这个连接。
  4. 客户主机正常运行,但是从服务器不可达。这与状态2相同,因为TCP不能够区分状态4与状态2之间的区别,它所能发现的就是没有收到探查的响应。

TCP/IP 协议详解 第21章 TCP的超时与重传

TCP通过确认从另一端收到数据来提供可靠的运输层,由于数据和确认都有可能丢失,TCP通过在发送时设置一个定时器来解决这种问题,当定时器溢出时还没有收到确认,它就重传该数据。对于任何实现而言,关键在于超时和重传的策略。

对于每个连接,TCP管理4个不同的定时器:

  • 重传定时器 使用于当希望收到另一端的确认。
  • 坚持(persist)定时器 使窗口大小信息保持不断流动,即使另一端关闭了其接收窗口。
  • 保活(keepalive)定时器 可检测到一个空闲连接的另一端何时崩溃或重启。
  • 2MSL定时器 测量一个连接处于 TIME_WAIT 状态的时间。

在进行超时重传时,两次重传的时间间隔是一个倍乘关系(每次增加1倍),称为“指数退避(exponential backoff)”。

继续阅读

TCP/IP 协议详解 第19、20章 TCP的数据流

第19章 交互数据流

交互数据总是以小于最大报文段长度(MSS,Maximum Segment Size)的分组(一般也称为微小分组,tinygram)发送。

经受时延的确认

通常TCP在收到数据时并不立即发送 ACK,它会推迟发送,以便将 ACK 与需要沿该方向发送的数据一起发送(这种现象也称为数据捎带 ACK)。绝大多数实现采用的时延是200ms。

Nagle 算法

Nagle 算法要求一个TCP连接上最多只能有一个未被确认的未完成的小分组,在该分组的确认到达之前不能发送其他的小分组。相反,TCP收集这些少量的分组,并在确认到来时以一个分组的方式发出去。该算法的优越之处在于它是自适应的:确认到达的越快,数据也就发送得越快。在希望减少微小分组数目的低速广域网上,则会发送更少的分组。

对于低延时的应用则需要关闭Nagle 算法,可以通过 TCP_NODELAY 选项来关闭。

在发送的报文段中如果包含了丢失的报文段中的数据,则称为重新分组化。

继续阅读