VC++编程之道读书笔记(2)
第三篇 技术细节
第七章:细说开发人员必知必会的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)的更多相关文章
- VC++编程之道读书笔记
第二篇 缪误21:位图数据是按照红绿蓝顺序存储的 大家都知道位图的颜色是由红.绿.蓝三个分量构成的,但是位图颜色数据存储的方式则不是按照这个顺序存储的,而是按照蓝.绿.红的顺序存储的.并且对于真彩色位 ...
- C语言编程之道--读书笔记
C语言语法 const int nListNum =sizeof(aPrimeList)/sizeof(unsigned);//计算素数表里元素的个数 1:#define INM_MAX 32767 ...
- 《Linux/Unix系统编程手册》读书笔记 目录
<Linux/Unix系统编程手册>读书笔记1 (创建于4月3日,最后更新4月7日) <Linux/Unix系统编程手册>读书笔记2 (创建于4月9日,最后更新4月10日) ...
- 《Linux/Unix系统编程手册》读书笔记9(文件属性)
<Linux/Unix系统编程手册>读书笔记 目录 在Linux里,万物皆文件.所以文件系统在Linux系统占有重要的地位.本文主要介绍的是文件的属性,只是稍微提及一下文件系统,日后如果有 ...
- 《Linux/Unix系统编程手册》读书笔记8 (文件I/O缓冲)
<Linux/Unix系统编程手册>读书笔记 目录 第13章 这章主要将了关于文件I/O的缓冲. 系统I/O调用(即内核)和C语言标准库I/O函数(即stdio函数)在对磁盘进行操作的时候 ...
- 《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)
<Linux/Unix系统编程手册>读书笔记 目录 第11章 这章主要讲了关于Linux和UNIX的系统资源的限制. 关于限制都存在一个最小值,这些最小值为<limits.h> ...
- 《Linux/Unix系统编程手册》读书笔记6
<Linux/Unix系统编程手册>读书笔记 目录 第9章 这章主要讲了一堆关于进程的ID.实际用户(组)ID.有效用户(组)ID.保存设置用户(组)ID.文件系统用户(组)ID.和辅助组 ...
- 《Linux/Unix系统编程手册》读书笔记5
<Linux/Unix系统编程手册>读书笔记 目录 第8章 本章讲了用户和组,还有记录用户的密码文件/etc/passwd,shadow密码文件/etc/shadow还有组文件/etc/g ...
- 《Linux/Unix系统编程手册》读书笔记4
<Linux/Unix系统编程手册>读书笔记 目录 第7章: 内存分配 通过增加堆的大小分配内存,通过提升program break位置的高度来分配内存. 基本学过C语言的都用过mallo ...
随机推荐
- ios的坑 无痕模式
我们的一个小应用,用localStorage做了下缓存,测试上线之后有反馈页面数据拉取不到, 最后定位到是localStorage有问题. 是Private Browsing Mode引起的.然后查看 ...
- JavaScript 复制内容到剪贴板
<html> <head> <title>Selector</title> <script language="javascript&q ...
- javaweb项目打成war包
进入项目文件 jar -cvf newsisAP.war *
- Java内存泄露原因详解
一.Java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.Java中对象是采用new或者反射的方法创建的, 这些对象的创建都是在堆(He ...
- 原创:微信小程序调用PHP后台接口,解析纯html文本
---效果图片预览--- 1.微信js动态传参:wx.request({ url: 'https://m.****.com/index.php/Home/Xiaoxxf/activ ...
- maven 亲测可用国内镜像 阿里云(20170123)
来源于:http://www.jianshu.com/p/4d5bb95b56c5 http://blog.csdn.net/qq_27093465/article/details/52982484 ...
- hdu4135容斥原理 组合遍历
容斥原理实现的关键在于:组合遍历,即如何遍历2^n种组合. 容斥原理的三种写法: DFS 队列数组 位数组 #include<stdio.h> #include<iostream&g ...
- jQuery DataTables的简单实现
DataTables是一个jQuery的表格插件.这是一个高度灵活的工具,依据的基础逐步增强,这将增加先进的互动控制,支持任何HTML表格. 主要特点: 1.自动分页处理 2.即时表格数据过滤 3.数 ...
- HTML5 API—无刷新更新地址 history.pushState/replaceState方法(例子) (转)
尽管是上面讲到的<JavaScript高级程序设计>(第二版)中提到,BOM中的location.path/query…… (window.location)在通过JavaScript更改 ...
- iOS - Bundle 资源文件包
1.Bundle 文件 Bundle 文件,简单理解,就是资源文件包.我们将许多图片.XIB.文本文件组织在一起,打包成一个 Bundle 文件.方便在其他项目中引用包内的资源. Bundle 文件是 ...