第三篇 技术细节

第七章:细说开发人员必知必会的39个开发细节

细节36:单例模式的应用

在开发程序时,往往需要在整个工程中只需要一个类的实例。而这个实例一旦被创建就不能被其他的实例再创建了,通常我们称这个实现过程为单例模式。

既然要保证类只有一个实例,那么就需要其他的类不能使用实例化该类。因此,需要将其构造方法设为私有的,即使用private关键字修饰。同时,类中提供一个静态方法,该方法的返回值是该类的一个实例。这样就只能使用该静态方法来获取类的实例了,从而保证了唯一性。

下面通过具体代码来实现一个单例模式的应用,代码如下:

 #include <iostream>
using namespace std; class Emperor
{
private:
static Emperor *pEmperor; // declear a reference
static int count; // contructor times
Emperor() // contructor
{
count++;
}
public:
static Emperor getInstance()
{
if(NULL == pEmperor)
{
pEmperor = new Emperor();
} return *pEmperor;
}
void getName()
{
cout << "I am the " << count << "contructor" << endl;
}
}
int main(void)
{
cout << "The first time contructor" << endl;
Emperor emperor1 = Emperor::getInstance();
emperor1.getName(); cout << "The second time contructor" << endl;
Emperor emperor2 = Emperor::getInstance();
emperor2.getName(); cout << "The third time contructor" << endl;
Emperor emperor3 = Emperor::getInstance();
emperor3.getName(); return ;
}

要想实现单例模式,首先,需要将类的构造方法定义为类的私有成员方法。当然,如果不是实现单例模式,这样做是不对的,因为在类外是无法创建该类的实例的。既然无法创建类的实例,那么单例模式又是如何创建这个类的实例的呢?方法很简单,在类中定义一个公有的静态成员方法,在这个静态成员方法中创建类的实例就可以了。

细节37:策略模式的简单应用

当我们在解决问题时,这个问题的解决方案有很多种,处理起来非常不方便。例如,在使用图像处理软件处理图片后,需要选择一种格式保存。然而各种格式在底层实现的算法并不相同,这刚好适合策略模式。

对于策略模式,需要定一个抽象类来标识各种策略的抽象。这样就可以使用多态来让虚拟机选择不同的实现类。然后让每一个中具体的策略来实现这个抽象,并为其中定义的方法提供具体的实现。由于在选择适当的策略上有些不方便,需要不断地判断需要的类型,因此用简单工厂方法类实现判断过程。

下面通过代码来看一下策略模式的应用,代码如下:

 #include <iostream>

 using namespace std;

 const int GIF = ;
const int JPEG = ;
// 抽象类
class ImageSaver
{
public:
virtual void save() = ; // 纯虚函数
}; class GIFSaver : public ImageSaver
{
public:
virtual void save()
{
cout << "将图片保存成GIF格式" << endl;
}
}; class JPEGSave : public ImageSaver
{
pbulic:
virtual void save()
{
cout << "将图片保存成JPEG格式" << endl;
}
}; class TypeChooser
{
public:
static ImageSaver* getSaver(int type)
{
if(type == GIF)
{
return new GIGSaver();
}
else if(type == JPEG)
{
return new JPEGSaver();
}
else
{
return null;
}
}
}; int main(void)
{
cout << "用户选择了GIF格式:" << endl;
ImageSaver *saver = TypeChooser::getSaver(GIF); // 获得保存图片为GIF类型的对象
saver->save();
cout << "用户选择了JPEG格式:" << endl;
delete saver;
saver = TypeChooser::getSaver(JPEG);
saver->saver(); return ;
}

在上面的代码中定义了接口ImageSaver,在该接口中定义了Save方法。接下来编写类GIFSaver类和JPEGSaver类,这两个类实现了ImageSaver接口。在实现save()方法时将图片保存成GIF和JPEG格式。编写类TypeChooser,该类根据用户提供的图片类型来选择合适的图片存储方式。这样就实现了一个简单的策略模式的应用。同时也使用了简单工厂模式。

细节38:适配器模式的使用

对于刚从工厂中生产出来的产品,有些功能并不能完全满足用户的需要。因此用户通常会对其进行一定的改装工作。在不破坏原有产品的情况下为其添加新的功能,这时就需要使用适配器模式。

适配器模式可以在符合OCP原则(开放封闭原则)的基础上,为类增加新的功能。该模式涉及的主要角色有以下几点。

  • 目标角色:就是期待得到的类,例如本实例的GPS抽象类。
  • 源角色:需要被增加功能的类,例如本实例的Car类。
  • 适配器角色:新创建的类,在源角色的基础上实现了目标角色,例如本实例的GPSCar类。

关于各个类的继承关系,如图1-1所示:

下面通过具体的实例来进一步了解适配器模式的应用,代码如下:

 #include <iostream>
#include <string> using namespace std; typedef char String[];
struct Point
{
int x, y;
}; class Car
{
private:
String name;
double speed;
public:
double getSpeed()
{
return speed;
}
void setSpeed(double sp)
{
this->speed = sp;
}
char *getName()
{
return name;
}
void setName(String strName)
{
strcpy(this->name, strName);
}
public:
virtual void toString()
{
cout << "车名:" << name << ", "
<< "速度:" << speed << "千米/小时" << endl;
}
};
class GPS
{
public:
virtual Point getLocation() = ; // 纯虚函数
}; class GSPCar : public Car, GPS
{
public:
Point getLocation()
{
Point point;
point.x = getSpeed();
point.y = getSpeed(); return point;
}
void toString()
{
Car::toString();
cout << "坐标:(" << getLocation().x << ", " << getLocation().y << ")" << endl;
}
}; int main(void)
{
cout << "自定义普通的汽车" << endl;
Car car;
car.setName("Audi");
car.setSpeed();
car.toString(); cout << "自定义GPS汽车" << endl;
GPSCar gpsCar;
gpsCar.setName("BMW");
gpsCar.setSpeed();
gpsCar.toString(); return ;
}

在上面的代码中产品是有Car类所标识的小汽车,新增加的功能是有GPS类标识的GPS定位功能。然后有适配器类GPSCar将Car类和GPS类组合到一起形成一个新的产品,这一过程就是适配器模式的使用。

VC++编程之道读书笔记(2)的更多相关文章

  1. VC++编程之道读书笔记

    第二篇 缪误21:位图数据是按照红绿蓝顺序存储的 大家都知道位图的颜色是由红.绿.蓝三个分量构成的,但是位图颜色数据存储的方式则不是按照这个顺序存储的,而是按照蓝.绿.红的顺序存储的.并且对于真彩色位 ...

  2. C语言编程之道--读书笔记

    C语言语法 const int nListNum =sizeof(aPrimeList)/sizeof(unsigned);//计算素数表里元素的个数 1:#define INM_MAX 32767 ...

  3. 《Linux/Unix系统编程手册》读书笔记 目录

    <Linux/Unix系统编程手册>读书笔记1  (创建于4月3日,最后更新4月7日) <Linux/Unix系统编程手册>读书笔记2  (创建于4月9日,最后更新4月10日) ...

  4. 《Linux/Unix系统编程手册》读书笔记9(文件属性)

    <Linux/Unix系统编程手册>读书笔记 目录 在Linux里,万物皆文件.所以文件系统在Linux系统占有重要的地位.本文主要介绍的是文件的属性,只是稍微提及一下文件系统,日后如果有 ...

  5. 《Linux/Unix系统编程手册》读书笔记8 (文件I/O缓冲)

    <Linux/Unix系统编程手册>读书笔记 目录 第13章 这章主要将了关于文件I/O的缓冲. 系统I/O调用(即内核)和C语言标准库I/O函数(即stdio函数)在对磁盘进行操作的时候 ...

  6. 《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)

    <Linux/Unix系统编程手册>读书笔记 目录 第11章 这章主要讲了关于Linux和UNIX的系统资源的限制. 关于限制都存在一个最小值,这些最小值为<limits.h> ...

  7. 《Linux/Unix系统编程手册》读书笔记6

    <Linux/Unix系统编程手册>读书笔记 目录 第9章 这章主要讲了一堆关于进程的ID.实际用户(组)ID.有效用户(组)ID.保存设置用户(组)ID.文件系统用户(组)ID.和辅助组 ...

  8. 《Linux/Unix系统编程手册》读书笔记5

    <Linux/Unix系统编程手册>读书笔记 目录 第8章 本章讲了用户和组,还有记录用户的密码文件/etc/passwd,shadow密码文件/etc/shadow还有组文件/etc/g ...

  9. 《Linux/Unix系统编程手册》读书笔记4

    <Linux/Unix系统编程手册>读书笔记 目录 第7章: 内存分配 通过增加堆的大小分配内存,通过提升program break位置的高度来分配内存. 基本学过C语言的都用过mallo ...

随机推荐

  1. spring-tool-suite(STS) 创建 spring boot项目

    1.创建一个Spring Starter Project工程(new --> Spring Starter Project) 2.选择自己需要的依赖,因为想要通过REST方式来验证是否成功创建, ...

  2. 获取TrustedInstaller

    Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\*\shell\runas] @="获取TrustedInstaller权限& ...

  3. OpenERP 在context中写自己的部门ID

    使用OpenERP自定义模块开发的时候,你会发现,有一个uid(当前登录用户id)特别好用,不管是在xml的domain 条件表达式中,还是在类中,都能很方便的使用uid.有一段时间就一直在琢磨,这个 ...

  4. How to set up OpenERP for various timezone kindly follow the following steps to select timezone in OpenERP

        How to set up OpenERP for different Time Zones Click on the "Edit Preferences" wheel a ...

  5. C#:定义窗口快捷键

    事情的关键是要设置Form的KeyPreview属性,然后再在KeyDown事件中检查按键. public class TEST : Form { public TEST() { Initialize ...

  6. HTTP 304状态分析

       在看http log日志发现很多304状态的标识 HTTP 304: Not Modified   ###请求后读取本地缓存的文件标准解释是:Not Modified 客户端有缓冲的文档并发出了 ...

  7. <%@ include file="">和<jsp:include file="">区别

    <%@include file="a.jsp"%>是在编译时加入,所谓静态,就是在编译的时候将jsp的代码加入进来再编译,之后运行. <jsp:include p ...

  8. Python的 numpy中 meshgrid 和 mgrid 的区别和使用

    一.meshgrid函数 meshgrid函数通常使用在数据的矢量化上. 它适用于生成网格型数据,可以接受两个一维数组生成两个二维矩阵,对应两个数组中所有的(x,y)对. 示例展示: 由上面的示例展示 ...

  9. 共享内存简介和mmap 函数

    一.共享内存简介 共享内存区是最快的IPC形式,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据. 即每个进程地址空间都有一个共享存储器的映射区,当这块区 ...

  10. Linux下C结构体初始化

    1.前言 今天在公司看一同事写的代码,代码中用到了struct,初始化一个struct用的是乱序格式,如下代码所示: typedef struct _data_t { int a; int b; }d ...