“对象创建”模式 - Factory Method | Abstract Factory | Prototype | Builder
“对象创建”模式:通过“对象创建”模式绕开 new 来避免对象创建过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象后的第一步工作。
Factory Method
Factory Method 也被称为 Virtual Constructor。
动机
在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。
如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?
定义
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer(目的:解耦;手段:虚函数) instantiation to subclasses.
实现
Naive
FileSplitter1.cpp
12345678910111213class ISplitter { public ...
“单一职责”模式 - Decorator | Bridge
“单一职责”模式:在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。
Decorator
Decorator 也被称为 Kit。
动机
在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
如何使“对象功能的扩展”能根据需要来动态地实现?同时避免“扩展功能的增多”带来子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响力将为最低?
定义
Attach(组合) additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing(继承) for extending functionality(消除重复代码 & 减少子类个数).
实现
Naive 编译时装载
1234567891011 ...
“组件协作”模式 - Template Method | Strategy | Observer
**"组件协作"模式:**现代软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式是通过晚期绑定,来实现框架和应用程序之间的松耦合,是二者之间协作常用的模式。
Template Method
动机
在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤去有很多改变的需求,或者由于固有原因(比如框架和应用之间的关系)而无法和任务的整体结构同时实现。
如果在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或晚期实现需求?
定义
Define the skeleton of an algorithm in an operation(稳定), deferring(变化) some steps to subclasses. Template Method lets subclass redefine(重写 override) certain steps of an algorithm without changing(复用) the algorithm’s structure.
实现
结构化软件设计流程
template1_li ...
经典并发问题- C/C++实现
同步问题:step1-2-3
Q: 对于如下的代码,如何使得 foo1 的 step1 和 step2 以及 foo2 中的 step3 按照 step1、2、3 的顺序执行:
12345678910111213141516void *foo1(void *) { printf("step 1 is done\n"); printf("step 3 is done\n");}void *foo2(void *) { printf("step 2 is done\n"); }int main() { pthread_t tid1; pthread_t tid2; Pthread_create(&tid1, NULL, foo1, NULL); Pthread_create(&tid2, NULL, foo2, NULL); Pthread_join(tid1, NULL); Pthread_join(tid2, NULL); exit(0);& ...
第16章 模板和泛型编程
面向对象编程和泛型编程都能处理在编写程序时不知道类型的情况。
OOP能处理类型在程序运行之前都未知的情况
泛型编程中,在编译时就需要获知类型
定义模板
模板:模板是泛型编程的基础。一个模板就是一个创建类或函数的蓝图或者说公式。
函数模板
template <typename T> int compare(const T &v1, const T &v2) {}
模板定义以关键字 template开始,后接模板形参表,模板形参表是用尖括号<>括住的一个或多个模板形参的列表,用逗号分隔,不能为空。
使用模板时,我们显式或隐式地指定模板实参,将其绑定到模板参数上。
模板类型参数:类型参数前必须使用关键字class或者typename,这两个关键字含义相同,可以互换使用。旧的程序只能使用class。
注意每个参数前都要加class或typename,比如这样是错误的:template <typename T, U> T calc(const T&, const U&); U之前必须加 ...
CSAPP - Shell Lab 详解
Shell Lab [Updated 7/28/03] (README, Writeup, Release Notes, Self-Study Handout)
Students implement their own simple Unix shell program with job control, including the ctrl-c and ctrl-z keystrokes, fg, bg, and jobs commands. This is the students’ first introduction to application level concurrency, and gives them a clear idea of Unix process control, signals, and signal handling.
前言
本篇博客将会详细介绍 CSAPP 之 ShellLab 的完成过程,实现一个简易(lou)的 shell。tsh 拥有以下功能:
可以执行外部程序
支持四个内建命令,名称和功能为:
quit:退出终端
jobs ...
第15章 面向对象程序设计
OOP:概述
面向对象程序设计(object-oriented programming)的核心思想是数据抽象、继承和动态绑定。
数据抽象:通过使用数据抽象,可以将类的接口和实现分离。
继承(inheritance):
通过继承联系在一起的类构成一种层次关系。
通常在层次关系的根部有一个基类(base class)。
其他类直接或者简介从基类继承而来,这些继承得到的类成为派生类(derived class)。
基类负责定义在层次关系中所有类共同拥有的成员,而每个派生类定义各自特有的成员。
对于某些函数,基类希望它的派生类个自定义适合自己的版本,此时基类就将这些函数声明成虚函数(virtual function)。
派生类必须通过使用类派生列表(class derivation list)明确指出它是从哪个基类继承而来。形式:一个冒号,后面紧跟以逗号分隔的基类列表,每个基类前都可以有访问说明符。class Bulk_quote : public Quote{};
派生类必须在其内部对所有重新定义的虚函数进行声明。可以在函数之前加上virtual关键字,也可以不加。C ...
第14章 重载运算与类型转换
基本概念
重载运算符是具有特殊名字的函数:由关键字operator和其后要定义的运算符号共同组成。
除了重载的函数调用运算符()外,其他重载运算符不能含有默认实参。
当一个重载的运算符是成员函数时,this绑定到左侧运算对象。动态运算符符函数的参数数量比运算对象的数量少一个。
只能重载大多数的运算符,而不能发明新的运算符号。
重载运算符的优先级和结合律跟对应的内置运算符保持一致。
调用方式:
data1 + data2;
operator+(data1, data2); 成员
data1.operator+=(data2); 非成员
运算符:
可以被重载
不可以被重载
+, -, *, /, %, ^
::, .*, ., ? :,
&, `
, ~`, `!`, `,`, `=`
<, >, <=, >=, ++, --
<<, >>, ==, !=, &&, `
+=, -=, /=, %=, ^=, &=
|=, *=, <<=, > ...
第13章 拷贝控制
拷贝控制操作(copy control)
拷贝构造函数(copy constructor)
拷贝赋值运算符(copy-assignment operator)
移动构造函数(move constructor)
移动赋值运算符(move-assignement operator)
析构函数(destructor)
拷贝和移动构造函数定义了当用同类型的另一个对象初始化本对象时做什么,拷贝和移动赋值运算符定义了将一个对象赋予同类型的另一个对象时做什么。
拷贝、赋值和销毁
拷贝构造函数
如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。
注意:拷贝构造函数的第一个参数必须是一个引用类型,虽然可以定义接受非const引用的拷贝构造函数,但此参数几乎总是一个const引用。
为什么要引用类型:拷贝构造函数被用来初始化非引用类类型参数(非引用形参采取值复制,复制会调用拷贝构造函数),如果其参数不是引用类型,那么调用永远不会成功——为了调用拷贝构造函数,必须拷贝其实参,但为了拷贝实参,我们又需要调用拷贝构造函数,如此无限循环。
cla ...
Archlinux WSL Segment Fault on Cypthon
先上结论:不要使用Archlinux WSL
重要的事情说三遍:
不要使用Archlinux WSL
不要使用Archlinux WSL
不要使用Archlinux WSL
看看Archlinux on WSL? / Other Architectures / Arch Linux Forums中大伙的评论:
It seems to be a set of initial unconfigured packages that you have to configure yourself.
It isn’t Arch, and it isn’t supported by the community.
Or is it maybe something unacceptable about it?
Correct, see http://archlinux.2023198.n4.nabble.com/ … l#a4718292
官方和社区都不支持,那还玩啥?
问题
下面给出一个我在使用ArchLinux WSL中遇到的问题:
当使用python运行一个使用了Cpython的脚本时,引 ...