Хорошей метафорой, если вы знакомы с шаблонами проектирования, является Decorator.В качестве примера я бы взял BufferedReader и любые другие типы ридеров.Таким образом, у вас есть базовый (и, возможно, не очень эффективный читатель), и вы хотите на лету, не заботясь о том, как сделать его буферизованным и повысить производительность, поэтому вы создаете BufferedReader, который оборачивает базовый объект Reader.
Концепция со стеками драйверов похожа - у вас может быть драйвер более низкого уровня, который будет записывать символы на устройство, НО вы можете подключить поверх него другой драйвер, который бы перемешивал каждый символ, который он получает, и, по сути, у вас есть целоестек шифрования.Таким образом, базовый драйвер ничего не знает обо всей этой «магии», которая происходит, он делает именно то, для чего он был создан - запись символов на блочное устройство.