VC++编程之道读书笔记(2)

第三篇 技术细节

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

细节36:单例模式的应用

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

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

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

 1 #include <iostream>
 2 using namespace std;
 3 
 4 class Emperor
 5 {
 6 private:
 7     static Emperor *pEmperor; // declear a reference
 8     static int count; // contructor times
 9     Emperor() // contructor
10     {
11         count++;
12     }
13 public:
14     static Emperor getInstance()
15     {
16         if(NULL == pEmperor)
17         {
18             pEmperor = new Emperor();
19         }
20         
21         return *pEmperor;
22     }
23     void getName()
24     {
25         cout << "I am the " << count << "contructor" << endl; 
26     }
27 }
28 int main(void)
29 {
30     cout << "The first time contructor" << endl;
31     Emperor emperor1 = Emperor::getInstance();
32     emperor1.getName();
33     
34     cout << "The second time contructor" << endl;
35     Emperor emperor2 = Emperor::getInstance();
36     emperor2.getName();
37     
38     cout << "The third time contructor" << endl;
39     Emperor emperor3 = Emperor::getInstance();
40     emperor3.getName();
41     
42     return 0;
43 }

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

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

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

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

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

 

 1 #include <iostream>
 2 
 3 using namespace std;
 4 
 5 const int GIF = 1;
 6 const int JPEG = 2;
 7 // 抽象类
 8 class ImageSaver
 9 {
10 public:
11     virtual void save() = 0; // 纯虚函数
12 };
13 
14 class GIFSaver : public ImageSaver
15 {
16 public:
17     virtual void save()
18     {
19         cout << "将图片保存成GIF格式" << endl;
20     }
21 };
22 
23 class JPEGSave : public ImageSaver
24 {
25 pbulic:
26     virtual void save()
27     {
28         cout << "将图片保存成JPEG格式" << endl;
29     }
30 };
31 
32 class TypeChooser
33 {
34 public:
35     static ImageSaver* getSaver(int type)
36     {
37         if(type == GIF)
38         {
39             return new GIGSaver();
40         }
41         else if(type == JPEG)
42         {
43             return new JPEGSaver();
44         }
45         else
46         {
47             return null;
48         }
49     }
50 };
51 
52 int main(void)
53 {
54     cout << "用户选择了GIF格式:" << endl;
55     ImageSaver *saver = TypeChooser::getSaver(GIF); // 获得保存图片为GIF类型的对象
56     saver->save();
57     cout << "用户选择了JPEG格式:" << endl;
58     delete saver;
59     saver = TypeChooser::getSaver(JPEG);
60     saver->saver();
61     
62     return 0;
63 }

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

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

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

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

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

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

 

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

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 typedef char String[30];
 7 struct Point
 8 {
 9     int x, y;
10 };
11 
12 class Car
13 {
14 private:
15     String name;
16     double speed;
17 public:
18     double getSpeed()
19     {
20         return speed;
21     }
22     void setSpeed(double sp)
23     {
24         this->speed = sp;
25     }
26     char *getName()
27     {
28         return name;
29     }
30     void setName(String strName)
31     {
32         strcpy(this->name, strName);
33     }
34 public:
35     virtual void toString()
36     {
37         cout << "车名:" << name << ", "
38         << "速度:" << speed << "千米/小时" << endl;
39     }
40 };
41 class GPS
42 {
43 public:
44     virtual Point getLocation() = 0; // 纯虚函数
45 };
46 
47 class GSPCar : public Car, GPS
48 {
49 public:
50     Point getLocation()
51     {
52         Point point;
53         point.x = getSpeed();
54         point.y = getSpeed();
55         
56         return point;
57     }
58     void toString()
59     {
60         Car::toString();
61         cout << "坐标:(" << getLocation().x << ", " << getLocation().y << "" << endl;
62     }
63 };
64 
65 int main(void)
66 {
67     cout << "自定义普通的汽车" << endl;
68     Car car;
69     car.setName("Audi");
70     car.setSpeed(100);
71     car.toString();
72     
73     cout << "自定义GPS汽车" << endl;
74     GPSCar gpsCar;
75     gpsCar.setName("BMW");
76     gpsCar.setSpeed(120);
77     gpsCar.toString();
78     
79     return 0;
80 }

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

posted @ 2014-05-13 07:37  冷冰若水  阅读(312)  评论(0编辑  收藏  举报