Рекомендую прочитать Чистый код глава 6: объекты и структуры данных.Вся глава об этом ... Вы можете прочитать реферат, если вы не хотите покупать книгу, ее можно найти здесь .
В соответствии с этим вы можете использоватьзанятия эффективно двумя разными способами.Это явление называется антисимметрией данных / объектов.В зависимости от ваших целей, вы должны решить, будут ли ваши классы следовать принципу открытый / закрытый или нет.
Если они следуют OCP, они будут полиморфными, а их экземпляры будут использоваться как объекты,Таким образом, они будут скрывать данные и реализацию общего интерфейса, и будет легко добавить новый тип, который также реализует этот интерфейс.Большинство шаблонов проектирования соответствуют OCP, например MVC, IoC, каждая оболочка, адаптер и т. Д. *
Если они не следуют OCP, они не будут полиморфными, их экземпляры будут использоваться в качестве данныхструктур.Таким образом, они будут предоставлять данные, и этими данными будут манипулировать другие классы.Это типичный подход и для процедурного программирования.Есть несколько примеров, в которых не используется OCP, например DTO, исключения, конфигурационные объекты, шаблон посетителя и т. Д.
Типичный шаблон, когда вы должны подумать о выполнении OCP и переместитькод для более низкого уровня абстракции:
class Manipulator {
doSomething(Object dataStructure){
if (dataStructure instanceof MyType1){
// doSomething implementation 1
}
else if (dataStructure instanceof MyType2)
{
// doSomething implementation 2
}
// ...
},
domSomethingElse(Object dataStructure){
if (dataStructure instanceof MyType1){
// domSomethingElse implementation 1
}
else if (dataStructure instanceof MyType2)
{
// domSomethingElse implementation 2
}
// ...
}
}
class MyType1 {}
class MyType2 {}
//if you want to add a new type, every method of the Manipulator will change
исправлено: перемещение реализации на более низкий уровень абстракции и выполнение OCP
interface MyType {
doSomething();
domSomethingElse();
}
class MyType1 implements MyType {
doSomething(){
// doSomething implementation 1
},
domSomethingElse(){
// domSomethingElse implementation 1
}
}
class MyType2 implements MyType {
doSomething(){
// doSomething implementation 2
},
domSomethingElse(){
// domSomethingElse implementation 2
}
}
// the recently added new type
class MyType3 implements MyType {
doSomething(){
// doSomething implementation 3
},
domSomethingElse(){
// domSomethingElse implementation 3
}
}
Типичный шаблон, когда вы должны подумать о нарушении OCP и переместить кодна более высокий уровень абстракции:
interface MyType {
doSomething();
domSomethingElse();
//if you want to add a new method here, every class which implements this interface, will be modified
}
class MyType1 implements MyType {
doSomething(){
// doSomething implementation 1
},
domSomethingElse(){
// domSomethingElse implementation 1
}
}
class MyType2 implements MyType {
doSomething(){
// doSomething implementation 2
},
domSomethingElse(){
// domSomethingElse implementation 2
}
}
или
interface MyType {
doSomething();
domSomethingElse();
}
class MyType1 implements MyType {
doSomething(){
// doSomething implementation 1
},
domSomethingElse(){
// domSomethingElse implementation 1
}
}
class MyType2 implements MyType {
doSomething(){
// doSomething implementation 2
},
domSomethingElse(){
// domSomethingElse implementation 2
}
}
//adding a new type by which one or more of the methods are meaningless
class MyType3 implements MyType {
doSomething(){
throw new Exception("Not implemented, because it does not make any sense.");
},
domSomethingElse(){
// domSomethingElse implementation 3
}
}
Исправлено: перемещение реализации на более высокий уровень абстракции и нарушение OCP
class Manipulator {
doSomething(Object dataStructure){
if (dataStructure instanceof MyType1){
// doSomething implementation 1
}
else if (dataStructure instanceof MyType2)
{
// doSomething implementation 2
}
// ...
},
domSomethingElse(Object dataStructure){
if (dataStructure instanceof MyType1){
// domSomethingElse implementation 1
}
else if (dataStructure instanceof MyType2)
{
// domSomethingElse implementation 2
}
// ...
},
// the recently added new method
doAnotherThing(Object dataStructure){
if (dataStructure instanceof MyType1){
// doAnotherThing implementation 1
}
else if (dataStructure instanceof MyType2)
{
// doAnotherThing implementation 2
}
// ...
}
}
class MyType1 {}
class MyType2 {}
или разделениеклассы в подклассы.
Люди обычно следуют OCP по количеству методов один или два, потому что повторять одни и те же операторы if-else недостаточно СУХОЙ.
Я не рекомендую использовать смешанные классыкоторые частично выполняют, частично нарушают OCP, потому что тогда код будет очень трудно поддерживать.Вы должны решить в каждой ситуации, какой подход вы придерживаетесь.Это обычно должно быть легким решением, но если вы допустили ошибку, вы все равно можете реорганизовать свой код позже ...