#include "stdio.h"
#include "stdlib.h"

typedef struct Module Module_t;
typedef struct{
    void (*Start)(Module_t*);
	void (*DoSomething)(Module_t*);
	void (*End)(Module_t*);
	void (*dtor)(Module_t*);
} ModuleVTable;

typedef struct {
	ModuleVTable *vtable;    
} Module;

void Module_Start(Module* this){
	this->vtable->Start(this);
}

void Module_DoSomeThing(Module* this){
	this->vtable->DoSomething(this);
}

void Module_End(Module* this){
	this->vtable->End(this);
}

void Delete_Module(Module* this){
	this->vtable->dtor(this);
	free(this);
}
typedef struct{
	Module base;
} ModuleA;

typedef struct{
	Module base;
} ModuleB;

static ModuleVTable ModuleA_vtable;
static ModuleVTable ModuleB_vtable;
void ModuleA_Start(ModuleA *this){
	printf("ModuleA.Start()\n");
}
void ModuleA_DoSomething(ModuleA *this){
	printf("ModuleA.DoSomething()\n");
}
void ModuleA_End(ModuleA *this){
	printf("ModuleA.End()\n");
}
void ModuleA_dtor(ModuleA *this){
	
}
ModuleA *New_ModuleA(){
	ModuleA *rst =(ModuleA*)malloc(sizeof(ModuleA));
	rst->base.vtable = &ModuleA_vtable;
	return rst;
}
void ModuleB_Start(ModuleB *this){
	printf("ModuleB.Start()\n");
}
void ModuleB_DoSomething(ModuleB *this){
	printf("ModuleB.DoSomething()\n");
}
void ModuleB_End(ModuleB *this){
	printf("ModuleB.End()\n");
}
void ModuleB_dtor(ModuleA *this){
	
}
ModuleB *New_ModuleB(){
	ModuleB *rst =(ModuleB*)malloc(sizeof(ModuleB));
	rst->base.vtable = &ModuleB_vtable;
	return rst;
}

void ModuleA_Initialize(){
	ModuleA_vtable.Start = &ModuleA_Start;
	ModuleA_vtable.DoSomething = &ModuleA_DoSomething;
	ModuleA_vtable.End = &ModuleA_End;
	ModuleA_vtable.dtor = &ModuleA_dtor;
}
void ModuleB_Initialize(){
	ModuleB_vtable.Start = &ModuleB_Start;
	ModuleB_vtable.DoSomething = &ModuleB_DoSomething;
	ModuleB_vtable.End = &ModuleB_End;
	ModuleB_vtable.dtor = &ModuleB_dtor;
}
int main(){
	Module *m;
	ModuleA_Initialize();
	ModuleB_Initialize();

	m = New_ModuleA();
	Module_Start(m);
	Module_DoSomeThing(m);
	Module_End(m);
	Delete_Module(m);

	m = New_ModuleB();
	Module_Start(m);
	Module_DoSomeThing(m);
	Module_End(m);
	Delete_Module(m);

	system("pause");
	return 0;
}