O Princípio Aberto-Fechado dita que toda e qualquer parte de um software - normalmente chamada de componente - deve ser aberta à extenção da sua funcionaldiade, mas fechada à sua modificação.
Este príncipio signficia que deve ser possivel aumentar as funcionalidades e capacidades do componente sem modificar o seu código.
A primeira técnica, utilizada para a implementação deste principio foi a herança. Uma classe A com uma certa funcionaldiade permite que seja herdada. A funciondalidade de A não depende de ser herdada e é toda autocontida em A. O seu código é fechado e pode ser colocada numa biblioteca à parte. Uma classe B pode então extender A e adicionar funcionalidade quando for necessário.
Esta técnica é limitda porque embora A não precise ser herdada, ela precisa ser desenhada para permitir a herança. A classe filha, qualquer que seja, precisa ter acesso ao estado da classe mãe para realmente poder extender as suas funcionaldidades.
Mais tarde, uma tecnica usando interfaces se tornou mais conveniente. Nesta tecnica é definida uma interface sem implementação. Assim o código da interface é fechado a modificação, mas a fucnionalidade pode ser implementada de várias formas, conforme necessário. Este técnica é a que está na base do padrão Service
.
Atualmente o Princípio Aberto-Fechado pode ser implementado recorrento à separação daquilo que é fixo, daquilo que é modificável. Normalmente a classe tem um algortimo fixo, em que algums passos podem ser modificados. Estes pedaços modificáveis podem ser modificados via herança ou via composição.
Via herança a classe estabelece métodos que são ppublicos e métodos que são acessiveis apenas às suas classes filhas. Estes métodos protegidos têm implementações simples ou até vazias. A classe chama esses métodos dentro dos algoritmos dos métodos públicos. A classe original é fechada a modificações e pode ser até colocada numa biblioteca à parte. Mas extensões são possiveis criando novas classes filhas. Este é o padrão Template Method
.
Via composição a classe estabelece uma outra interface diferente da sua e permite que objetos com essa inferface sejam registrados com ela. Pode ser um ou mais objetos destes dependendo do objetivo em mãos. A outra interface pode ser implementada à parte. As instâncias da interface registradas serão invocadas em algum ponto do código da classe principal. Esta tecnica é usada, por exemplo, no padrão Observer
.
Outra forma de compor é utilizando objetos funcionais conhecidos como closures ou lambdas. Estes são objetos que só contém uma única função. A classe principal recebe estes objetos e os invoca em momentos espeficios. Esta é a técnica usada em Monads - como Optional e Stream - em que a implementação do monad é fixa, mas as transformações que podem ser feitas são completamente extensiveis.
O Príncipio Aberto-Fechado foi identificado por Bertrand Meyer em 1988 no seu livro "Object Oriented Software Construction".
Ele chama as partes do software de "modulos" e se refere ao que hoje chamamos de classes.
A forma utilizada por Bertrand para a implementação deste principio é usando herança. Ele se referia também a poder extender a classe adicionando propriedades e não apenas métodos. A técnica uando interfaces de popularizou nos anos 1990. Em 1996 Robert C. Martin escreveu um artigo que popularizou o conceito.
Também pela mão de Robert C. Martin este princípio entrou para o top 5 dos Principios de Orientação de Objetos, juntos conhecidos como os "Principios SOLID" (SOLID Principles) num trocadilho de palavras sugerindo que seguir os princípios SOLID, tornaria o código sólido, por oposição a frágil. O Princípio Aberto-Fechado corresponde ao O pelo seu nome em inglês: Open-close Principle.