功能与API的分离封装
原始需求
Python中的一个类封装了各种操作,需要对外提供组合各种操作的接口,为了将操作与接口分开,且易于扩展。
- 操作与接口分开:Process类与Api类。Process封装操作内容,Api类对操作进行组合
- 易于扩展:Process::parse()中的apis添加了操作名称与对应函数的映射。parse()也可以移动到Api类中。添加新接口时只需在Api类中添加对应的函数、apis中添加名称映射即可。
不知道是不是某个设计模式(类似于某个工厂模式,不过应该不算是吧)。
Python支持动态绑定,可以嵌套生成,不嵌套调用就行。
用C++简单实现了一下,list跟map创建比较麻烦,坑也比较多。例子粗糙,但基本功能已经实现。
- pyhton
class Process(object):
def __init__(self, api):
self.__api = api
self.__hello = 'hello'
self.__world = 'world'
def hello(self):
return self.__hello
def world(self):
return self.__world
def parse(self, args):
apis = {'hello_world': self.__api.hello_world, 'world_hello': self.__api.world_hello}
for arg in args:
if arg in apis:
apis[arg]()
else:
print('找不到命令:{}'.format(arg))
class Api(object):
def __init__(self):
self.__process = Process(self)
def hello_world(self):
print('{} {}'.format(self.__process.hello(), self.__process.world()))
def world_hello(self):
print('{} {}'.format(self.__process.world(), self.__process.hello()))
def run(self):
args = ['hello_world', 'world_hello', 'HelloWorld']
self.__process.parse(args=args)
api = Api()
api.run()
- c++
// $ g++ process.cpp -o ./process --std=c++11 -g
// $ ./process
// hello world
// Api::~Api() _process : 0x0x7fab2f705b70
// world hello
// Api::~Api() _process : 0x0x7fab2f705b70
// 找不到命令:HelloWorld
// Api::~Api() _process : 0x0x7fab2f705b70
#include <iostream>
#include <list>
#include <map>
#include <functional> // bind
using namespace std;
class Api;
class Process
{
public:
Process(const Api*api):_api(api){}
const string& hello() {
return _hello;
}
const string& world() {
return _world;
}
void parse(const list<string>&options);
private:
const Api *_api;
const string _hello = "hello";
const string _world = "world";
};
class Api
{
public:
Api() {
_process = new Process(this);
}
~Api() {
cout << "Api::~Api() _process : 0x" << hex << (void*)_process << endl;
}
void hello_world() {
cout << _process->hello() << " " << _process->world() << endl;
}
void world_hello() {
cout << _process->world() << " " << _process->hello() << endl;
}
void run() {
const list<string> options = {"hello_world", "world_hello", "HelloWorld"};
_process->parse(options);
}
private:
Process *_process = nullptr;
};
inline void Process::parse(const list<string>&options) {
auto ra1 = &Api::hello_world;
auto ra2 = &Api::world_hello;
map<string, decltype(ra1)> kv;
kv.insert(make_pair(string("hello_world"), ra1));
kv.insert(make_pair(string("world_hello"), ra2));
for(auto option:options) {
auto itea = kv.find(option);
if(itea != kv.end()) {
auto bd = bind((*itea).second, *_api);
bd(); // Api::~Api()
}
else{
cout << "找不到命令:" << option << endl;
}
}
}
int main() {
Api api;
api.run();
return 0;
}