如无特殊声明:本文所有 UML 图均出自《图说设计模式》。在此特别鸣谢!

Singleton

单例模式解决了全局变量的问题,全局只能创建一个实例,保证任何请求该实例的调用均返回同一个对象,保证不会被意外析构。

singleton

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// A singleton class
// c.f. https://zhuanlan.zhihu.com/p/37469260

/**
 * This is so-called lazy-singleton, since it creates the
 * instance until you ask for it.
 *
 * However, it may cause memory leak, since you have no
 * way to delete the instance you created.
 */
class SingletonV1
{
public:
  static SingletonV1* GetInstance()
  {
    if (pinstance_ == nullptr)
      pinstance_ = new SingletonV1();
    return pinstance_;
  }
private:
  SingletonV1() = default;
  ~SingletonV1() = default;
  SingletonV1(const SingletonV1&) = delete;
  SingletonV1& operator=(const SingletonV1&) = delete;
private: 
  static SingletonV1* pinstance_;
};
// static member initialization
SingletonV1* SingletonV1::pinstance_ = nullptr;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <mutex>
using namespace std;

std::mutex gm;

/**
 * This is also a lazy-singleton, but it's thread-safe.
 * It is so-called Double-Checked Locking Pattern (DCL).
 */
class SingletonV2
{
public:
  static SingletonV2* GetInstance()
  {
    if (pinstance_ == nullptr)
    {
      // Attention here: see if >= 2 threads meets here,
      // only one thread can hold the mutex, then create
      // the instance, this is can only occur on your first
      // request on instance, once the instance is created,
      // we can return it immediately.
      std::lock_guard<std::mutex> lk(gm);

      // See why double check here?
      // Cause if >= 2 threads have already run across here,
      // they've waited and finally held the mutex, w/o this
      // check, all of these threads will create a instance,
      // that's not what you want.
      if (pinstance_ == nullptr)  // double check
        pinstance_ = new SingletonV2();
    }
    return pinstance_;
  }
private:
  SingletonV2() = default;
  ~SingletonV2() = default;
  SingletonV2(const SingletonV2&) = delete;
  SingletonV2& operator=(const SingletonV2&) = delete;
private: 
  static SingletonV2* pinstance_;
};
// static member initialization
SingletonV2* SingletonV2::pinstance_ = nullptr;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/**
 * C++11 ensures the mt-safety of local static object. Taking
 * the advantage of this, <<Effective C++>> provides us an elegant
 * implemention of mt-safe singleton.
 */
class SingletonV3
{
public:
  static SingletonV3* GetInstance()
  {
    // Note that instance will be created only at the first time.
    static SingletonV3 instance;
    return &instance;
  }
private:
  SingletonV3() = default;
  ~SingletonV3() = default;
  SingletonV3(const SingletonV3&) = delete;
  SingletonV3& operator=(const SingletonV3&) = delete;
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * This is an eager-singleton which create an instance at first,
 * then return it as required.
 *
 * It's mt-safe since the instance initiliazation is before main()
 * function.
 */
class SingletonV4
{
public:
  static SingletonV4* GetInstance()
  {
    return &instance_;
  }
private:
  SingletonV4() = default;
  ~SingletonV4() = default;
  SingletonV4(const SingletonV4&) = delete;
  SingletonV4& operator=(const SingletonV4&) = delete;
private:
  // note that here is not a pointer, since a pointer will not own
  // a memory range by default.
  static SingletonV4 instance_;
};
// initialize the static member
SingletonV4 SingletonV4::instance_;

Factory

工厂模式将对象的创建和对象本身的业务分离,适合那些不关心对象如何创建,对象的创建相对独立的情形。工厂模式又分三种,谓之工厂三兄弟:

  1. Simple Factory
  2. Factory Method
  3. Abstract Factory

Simple Factory

简单工厂模式就是有一个工厂类,你给我什么参数我就给你创造什么对象。

simple factory

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// This file implements a demo for simple factory pattern.
//
#include <cstdio>
#include <string>

#define PRINT_NAME printf("%s\n", __FUNCTION__)

using namespace std;

class Product // abstract product
{
public:
  virtual ~Product() { PRINT_NAME; }
public:
  virtual void Operation() = 0;
};

class ProductA : public Product // concrete product
{
public:
  ~ProductA() { PRINT_NAME; }
public:
  void Operation() override { printf("%s\n", "A::Operation()"); }
};

class ProductB : public Product // concrete product
{
public:
  ~ProductB() { PRINT_NAME; }
public:
  void Operation() override { printf("%s\n", "B::Operation()"); }
};

class Factory // factory
{
public:
  ~Factory() { PRINT_NAME; }
public:
  static Product* CreateProduct(const string& name)
  {
    if (name == "A")
      return new ProductA();
    else if (name == "B")
      return new ProductB;
    else
      return nullptr;
  }
};

///
int main()
{
  Product* pa = Factory::CreateProduct("A");
  Product* pb = Factory::CreateProduct("B");
  pa->Operation();
  pb->Operation();

  delete pb;
  delete pa;
  return 0;
}

Factory Method

工厂方法模式,是指有一个抽象工厂,他不负责实际的创建任务,所有不同类型的对象由其不同的子类创建。

factory method

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <cstdio>

#define PRINT_NAME printf("%s\n", __FUNCTION__)

class Product
{
public:
  virtual ~Product() { PRINT_NAME; }
public:
  virtual void Operation() = 0;
};

class ProductA : public Product
{
public:
  ~ProductA() { PRINT_NAME; }
public:
  void Operation() override
  {
    printf("%s\n", "ProductA::Operation()");
  }
};

class ProductB : public Product
{
public:
  ~ProductB() { PRINT_NAME; }
public:
  void Operation() override
  {
    printf("%s\n", "ProductB::Operation()");
  }
};

class Creator
{
public:
  virtual ~Creator() { PRINT_NAME; }
public:
  virtual Product* CreateProduct() = 0;
};

class CreatorA : public Creator
{
public:
  ~CreatorA() { PRINT_NAME; }
public:
  Product* CreateProduct() override
  {
    return new ProductA();
  }
};

class CreatorB : public Creator
{
public:
  ~CreatorB() { PRINT_NAME; }
public:
  Product* CreateProduct() override
  {
    return new ProductB();
  }
};

// test
int main()
{
  Creator* ca = new CreatorA;  
  Product* pa = ca->CreateProduct();
  pa->Operation();

  Creator* cb = new CreatorB;
  Product* pb = cb->CreateProduct();
  pb->Operation();

  delete pb;
  delete cb;
  delete pa;
  delete ca;
  return 0;
}

Abstract Factory

抽象工厂模式,是指有一个抽象工厂,他不负责实际的创建任务。它会有很多个子类,每个子类负责创建一族具有某种特定属性的对象。如果把工厂所需要创建的对象称为产品,同样有一个抽象产品,他有多个子类,代表不同产品,但每一个产品又有不同属性。所以,把具有相同属性的所有产品的创建任务交给一个工厂(抽象工厂的一个子类),把具有另一个属性的所有产品的创建任务交给另一个工厂(抽象工厂的另一个子类)。

abstract factory

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
// This file implements a demo of abstract factory pattern.
//
#include <cstdio>

#define PRINT_NAME printf("%s\n", __FUNCTION__)

// cats
class Cat
{
public:
  virtual ~Cat() { PRINT_NAME; }
public:
  virtual void Meow() = 0;
};

class BlackCat : public Cat
{
public:
  ~BlackCat() { PRINT_NAME; }
public:
  void Meow() override { printf("%s\n", "b::meow~"); }
};

class WhiteCat : public Cat
{
public:
  ~WhiteCat() { PRINT_NAME; }
public:
  void Meow() override { printf("%s\n", "w::meow~"); }
};

// dogs
class Dog
{
public:
  virtual ~Dog() { PRINT_NAME; }
public:
  virtual void Bark() = 0;
};

class BlackDog : public Dog
{
public:
  ~BlackDog() { PRINT_NAME; }
public:
  void Bark() override { printf("%s\n", "b::wang~"); }
};

class WhiteDog : public Dog
{
public:
  ~WhiteDog() { PRINT_NAME; }
public:
  void Bark() override { printf("%s\n", "w::wang~"); }
};

// here comes factory
class Factory
{
public:
  virtual ~Factory() { PRINT_NAME; }
public:
  virtual Cat* CreateCat() = 0;
  virtual Dog* CreateDog() = 0;
};

class BlackFactory : public Factory  // factory that dyes animals black
{
public:
  ~BlackFactory() { PRINT_NAME; }
public:
  Cat* CreateCat() override { return new BlackCat(); }
  Dog* CreateDog() override { return new BlackDog(); }
};

class WhiteFactory : public Factory  // factory that dyes animals white
{
public:
  ~WhiteFactory() { PRINT_NAME; }
public:
  Cat* CreateCat() override { return new WhiteCat(); }
  Dog* CreateDog() override { return new WhiteDog(); }
};

///
int main()
{
  Factory* pblack = new BlackFactory();
  Factory* pwhite = new WhiteFactory();

  Cat* black_cat = pblack->CreateCat();
  Cat* white_cat = pwhite->CreateCat();

  Dog* black_dog = pblack->CreateDog();
  Dog* white_dog = pwhite->CreateDog();

  black_cat->Meow();
  black_dog->Bark();
  white_cat->Meow();
  white_dog->Bark();

  delete white_dog;
  delete black_dog;
  delete white_cat;
  delete black_cat;
  delete pwhite;
  delete pblack;
  return 0;
}

Observer

观察者模式很重要,在计算机系统里有大量应用。就是说有一群观察者,希望观察某个目标,进而相应的动作。比方说很多人需要了解天气预报的信息,那么天气预报就是观察目标,如果人们知道天气预报说下雨,那么他可能会带把伞。这就是相应的操作。如何更新目标的状态是个很有意思的问题。常见的有两种,一是观察目标发生变化,主动通知所有的观察者;而是观察者不断轮询,监听观察目标,一旦发生变化,立刻做出相应的动作。前者称为 reactor,后者称为 proactor. 两种方式各有所用!比方说,如果订阅天气预报的人数寥寥无几,那么气象站完全可以向所有订阅者推送天气更新信息,但是如果全国上亿人都订阅了天气预报,那么此时完全推送可能就代价太大了。而有些订阅者,他时刻关注天气,比如地方气象站,而有些订阅者,他对实时性不要求那么高,比方说天气预报 APP(通常 1-2 小时更新一次),对于这两种不同的订阅者,很显然需要两种不同的更新方式:前者轮询,后者推送。

observer

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// This file implements a demo of observer pattern.
//
#include <cstdio>
#include <list>
#include <string>

#define PRINT_NAME printf("%s\n", __FUNCTION__)

// front declaration
class Subject;
class Observer;

class Subject
{
public:
  virtual ~Subject() { PRINT_NAME; }

public:
  virtual void attach(Observer* ob);
  virtual void detach(Observer* ob);
  virtual void notify();  // notify all observers
  
  virtual void set_state(int state) = 0;
  virtual int get_state() = 0;

private:
  std::list<Observer*> observers_;
};

class Observer
{
public:
  virtual ~Observer() { PRINT_NAME; }
public:
  virtual void update(Subject* sb) = 0;
};

//================ impl subject ==============
void Subject::attach(Observer* ob) { observers_.push_back(ob); }

void Subject::detach(Observer* ob)
{
  for (auto it = observers_.begin(); it != observers_.end(); ++it)
  {
    if (*it == ob)
    {
      observers_.erase(it);
      break;
    }
  }
}

void Subject::notify()
{
  for (auto ob : observers_)
    ob->update(this);
}

/* a specific subject */
class Weather : public Subject
{
public:
  ~Weather() { PRINT_NAME; }

public:
  void set_state(int s) override { state_ = s; }
  int get_state() override { return state_; }

private:
  int state_;
};

/* a specific observer */
class WeatherAPP : public Observer
{
public:
  WeatherAPP(const std::string& name): name_(name) {}
  ~WeatherAPP() { PRINT_NAME; }

public:
  void update(Subject* sb) override
  {
    state_ = sb->get_state(); 

    printf("Observer %s: ", name_.data());
    switch (state_)
    {
      case 0: printf("default\n");
              break;
      case 1: printf("rainy\n");
              break;
      case 2: printf("cloudy\n");
              break;
      case 3: printf("foggy\n");
              break;
      default: break;
    }
  }

private:
  int state_;
  std::string name_;
};

///
int main()
{
  Subject* weather = new Weather();
  Observer* ob1 = new WeatherAPP("Color TianQi");
  Observer* ob2 = new WeatherAPP("Moji TianQi");
  weather->attach(ob1);
  weather->attach(ob2);

  weather->set_state(1); // rainy
  weather->notify();

  weather->detach(ob2);
  weather->set_state(3); // foggy
  weather->notify();
  
  delete ob2;
  delete ob1;
  delete weather;
  return 0;
}

References

  1. 图说设计模式