Ну, вы можете иметь обе вещи, т.е. создать абстрактный обобщенный класс. Я бы предпочел универсальный интерфейс, реализованный универсальным классом и созданный для конкретного типа за фабричным методом / классом. Абстрактный класс заставит создавать производные классы, делая его более утомительным. Пример использования, который я имею в виду, выглядит примерно так:
IPool<MyClass> = PoolFactory.Get<MyClass>(5); // 5 being pool size
IPool<IFoo> = PoolFactory.Get<FooImpl>(5);
IPool<IBar> = PoolFactory.Get(5, () => new BarImpl("some argument")); // instance creation with factory method
Обратите внимание, что это все еще может оставить мне область для специализации путем наследования от универсального класса - типичной потребностью будет сложное создание экземпляра (конечно, можно смоделировать, предоставив реализацию пула с фабричным интерфейсом или фабричным делегатом)