Further reorganize code and create abstract classes