天天看點

注冊回調機制代替switch case

最近開發中用來很多級聯的if-else和switch case,在這樣的代碼中,如果你想增加新的功能,必定會在原來的代碼下接着增加if-else或者case,這樣不符合“封閉開放原則”,因為修改了自己寫好的類。下面介紹下自己優化的思路。

1、典型的switch case場景

#include <stdio.h>
enum class User { //定義三個使用者
  jiongkai = 0,
  sywei = 1,
  zj = 2,
};
int main() {
  User user = User::jiongkai;
  switch (user) //不同的使用者,有不同的操作(op)
  {
  case User::jiongkai:
    printf("hello jiongkai\n");//假設操作為簡單的if-else
    break;
  case User::sywei:
    printf("hello sywei\n");
    break;
  case User::zj:
    printf("hello Zj\n");
    break;
  default:
    break;
  }
}
           

2、注冊回調機制的初步使用

#include <stdio.h>
enum class User {
  jiongkai = 0,
  sywei = 1,
  zj = 2,
};
void JiongKaiOp() {
  printf("hello jiongkai\n");
}
void SyweiOp() {
  printf("hello sywei\n");
}
void ZjOp() {
  printf("hello zj\n");
}
typedef void(*pfunc)();//定義一個函數指針
pfunc PFuncArr[10];//定義個函數指針數組
void Register() {//将swtich case下的每個op獨立為一個函數,并把函數指針儲存在函數指針數組中
  PFuncArr[(int)User::jiongkai] = JiongKaiOp;
  PFuncArr[(int)User::sywei] = SyweiOp;
  PFuncArr[(int)User::zj] = ZjOp;
}
int main() {
  User user = User::jiongkai;
  Register();
  PFuncArr[(int)user]();//根據user,取出對應的函數指針即可,這樣主函數中就不再需要switch case了
}
           

3、由面向過程到面向對象

#include <stdio.h>
enum class User {
  jiongkai = 0,
  sywei = 1,
  Zj = 2,
};
class ManageUsers {
private:
  typedef void(*pfunc)();
  pfunc PFuncArr[10];
public:
  void Register() {
    PFuncArr[(int)User::jiongkai] = JiongkaiOp;
    PFuncArr[(int)User::sywei] = syweiOp;
    PFuncArr[(int)User::Zj] = zjOp;
  }
  static void JiongkaiOp() {
    printf("hello jiokngkai\n");
  }
  static void syweiOp() {
    printf("hello sywei\n");
  }
  static void zjOp() {
    printf("hello zj\n");
  }
  void UserOp(int user) {
    PFuncArr[user]();
  }
};
int main() {
  User user = User::jiongkai;
  ManageUsers manager;
  manager.Register();
  manager.UserOp((int)user);
}
           

3.2 使用非靜态成員函數

/********************由面向過程到面向對象*********************************/
#include <stdio.h>
enum class User {
  jiongkai = 0,
  sywei = 1,
  zj = 2,
};
class ManageUsers {
private:
  typedef void(ManageUsers::*pfunc)();
  pfunc PFuncArr[10];
public:
  void Register() {
    PFuncArr[(int)User::jiongkai] = &ManageUsers::JiongkaiOp;
    PFuncArr[(int)User::sywei] = &ManageUsers::SyweiOp;
    PFuncArr[(int)User::zj] = &ManageUsers::ZjOp;
  }
  void JiongkaiOp() {
    printf("hello jiokngkai\n");
  }
  void SyweiOp() {
    printf("hello sywei\n");
  }
  void ZjOp() {
    printf("hello zj\n");
  }
  void UserOp(int user) {
    (this->*PFuncArr[user])();
  }
};
int main() {
  User user = User::jiongkai;
  ManageUsers manager;
  manager.Register();
  manager.UserOp((int)user);
}
           

4、封閉開放原則(将靜态成員函數進一步封裝成類)

#include <stdio.h>
#include <map>
using namespace std;
enum class UserName {
  jiongkai = 0,
  sywei = 1,
  zj = 2,
};

class User{
protected:
  int name;
public:
  virtual void Op() {};
};

class UsersRegister {
private:
  map<int,User*>UsersMap;
  static UsersRegister* instance;
  UsersRegister(){};
public:
  static  UsersRegister*GetInstance() {
    if(instance==NULL) {
      instance = new UsersRegister();
    }
    return instance;
  }
  void Register(User *user,int name) {
    UsersMap[name] = user;
  }
  void GetUser(int name) {
    UsersMap[name]->Op();
  }
};
UsersRegister* UsersRegister::instance = NULL;

class Jiongkai : public User{
public:
  Jiongkai(){
    name = (int)UserName::jiongkai;
  }
  void Op() {
    printf("hello jiokngkai\n");
  }
};

int main() {
  UserName user = UserName::jiongkai;
  Jiongkai *puser = new Jiongkai;//建立一個使用者
  UsersRegister::GetInstance()->Register(puser,(int)user);//将使用者注冊進去
  UsersRegister::GetInstance()->GetUser((int)user);
}
           

4.2 、初步優化(在構造函數中自動完成注冊)

#include <stdio.h>
#include <map>
using namespace std;
enum class UserName {
  jiongkai = 0,
  sywei = 1,
  zj = 2,
};

class User{
protected:
  int name;
public:
  virtual void Op() {};
};

class UsersRegister {
private:
  map<int,User*>UsersMap;
  static UsersRegister* instance;
  UsersRegister(){};
public:
  static  UsersRegister*GetInstance() {
    if(instance==NULL) {
      instance = new UsersRegister();
    }
    return instance;
  }
  void Register(User *user,int name) {
    UsersMap[name] = user;
  }
  void GetUser(int name) {
    UsersMap[name]->Op();
  }
};
UsersRegister* UsersRegister::instance = NULL;

class Jiongkai : public User{
public:
  static Jiongkai * instance;
  Jiongkai(){
    name = (int)UserName::jiongkai;
    UsersRegister::GetInstance()->Register(this,name);
  }
  void Op() {
    printf("hello jiokngkai\n");
  }
};
Jiongkai* Jiongkai::instance = new Jiongkai();

class Sywei : public User{
public:
  static Sywei* instance;
  Sywei(){
    name = (int)UserName::sywei;
    UsersRegister::GetInstance()->Register(this,name);
  }
  void Op() {
    printf("hello Sywei\n");
  }
};
Sywei* Sywei::instance = new Sywei();

int main() {
  srand((unsigned)time(NULL));
  UserName user = UserName(rand()%2);//随機建立一個使用者
  UsersRegister::GetInstance()->GetUser((int)user);
}

           

5、進一步優化(注冊方法,不注冊生成的好的指針)

#include <stdio.h>
#include <map>
using namespace std;
enum class UserName {
  jiongkai = 0,
  sywei = 1,
  zj = 2,
};

class User{
protected:
  int name;
public:
  virtual void Op() {};
};

class Factory{
public:
  virtual User* CreatUser() {};
};

class UsersRegister {
private:
  map<int,Factory*>UsersMap;
  static UsersRegister* instance;
  UsersRegister(){};
public:
  static  UsersRegister*GetInstance() {
    if(instance==NULL) {
      instance = new UsersRegister();
    }
    return instance;
  }
  void Register(Factory *user,int name) {
    UsersMap[name] = user;
  }
  void GetUser(int name) {
    UsersMap[name]->CreatUser()->Op();
  }
};
UsersRegister* UsersRegister::instance = NULL;

class Jiongkai : public User{
public:
  Jiongkai(){
    name = (int)UserName::jiongkai;
  }
  void Op() {
    printf("hello jiokngkai\n");
  }
};

class JiongkaiFactory : public Factory {
public:
  static JiongkaiFactory *instance;
  User* CreatUser() {
    return new Jiongkai;
  }
  JiongkaiFactory() {
    UsersRegister::GetInstance()->Register(this,(int)UserName::jiongkai);
  }
};
JiongkaiFactory* JiongkaiFactory::instance = new JiongkaiFactory;

int main() {
  srand((unsigned)time(NULL));
  UserName user = UserName(rand()%1);//随機建立一個使用者
  UsersRegister::GetInstance()->GetUser((int)user);
}
}
           

繼續閱讀