abstract factory + tests