Если в вашем коде много операторов switch / case, и они сводят вас с ума.
Вы можете выбрать Рефакторинг: Заменить условный полиморфизм.
Допустим, у вас есть часть программного обеспечения, которая используется для сохранения информации на разных устройствах: определены 4 операции сохранения: извлечение, сохранение, удаление, обновление , которое может Реализовано число механизмов сохранения (плоские файлы, сеть, RDBMS, XML и т. д.).
Ваш код должен поддерживать их все, поэтому в 4 разных местах у вас есть это:
до
class YourProblematicClass {
....
public void fetchData( Object criteria ) {
switch ( this.persitanceType ) {
case FilePersistance:
// open file
// read it
// find the criteria
// build the data
// close it.
break;
case NetWorkPersistance:
// Connect to the server
// Authenticate
// retrieve the data
// build the data
// close connection
break();
case DataBasePersistace:
// Get a jdbc connection
// create the query
// execute the query
// fetch and build data
// close connection
break;
}
return data;
}
То же самое для сохранения / удаления / обновления
public void saveData( Object data) {
switch ( this.persitanceType ) {
case FilePersistance:
// open file, go to EOF, write etc.
break;
case NetWorkPersistance:
// Connect to the server
// Authenticate
// etc
break();
case DataBasePersistace:
// Get a jdbc connection, query, execute...
break;
}
}
И так далее ...
public void deleteData( Object data) {
switch ( this.persitanceType ) {
case FilePersistance:
break;
case NetWorkPersistance:
break();
case DataBasePersistace:
break;
}
}
public void updateData( Object data) {
switch ( this.persitanceType ) {
case FilePersistance:
break;
case NetWorkPersistance:
break();
case DataBasePersistace:
break;
}
}
Использование оператора switch / case становится проблематичным:
Каждый раз, когда вы хотите добавить новый тип, вы должны вставить новый переключатель / корпус в каждый раздел.
Много раз, некоторые типы похожи, и им не нужен другой переключатель / случай (вы могли бы их каскадировать)
- Некоторые другие, и иногда они немного отличаются
- Возможно, вам даже потребуется загрузить другой тип во время выполнения (например, плагины)
Таким образом, рефакторинг здесь будет заключаться в добавлении интерфейса или абстрактного типа, а различные типы реализуют этот интерфейс и делегируют ответственность этому объекту.
Итак, у вас будет что-то вроде этого:
ПОСЛЕ
public interface PersistenceManager {
public void fetchData( Object criteria );
public void saveData( Object toSave );
public void deleteData( Object toDelete );
public void updateData( Object toUpdate );
}
И разные реализации
public class FilePersistence implements PersistanceManager {
public void fetchData( Object criteria ) {
// open file
// read it
// find the criteria
// build the data
// close it.
}
public void saveData( Object toSave ) {
// open file, go to EOF etc.
}
public void deleteData( Object toDelete ){
....
}
public void updateData( Object toUpdate ){
....
}
}
И другие типы будут реализовывать в соответствии с их логикой. Сеть будет работать с сокетами и потоками, БД будет работать с JDBC, ResultSets и т. Д. XML с узлом и т. Д. И т. Д.
public class NetworkPersistence implements PersistanceManager {
public void fetchData( Object criteria ) {
// Socket stuff
}
public void saveData( Object toSave ) {
// Socket stuff
}
public void deleteData( Object toDelete ){
// Socket stuff
}
public void updateData( Object toUpdate ){
// Socket stuff
}
}
public class DataBasePersistence implements PersistanceManager {
public void fetchData( Object criteria ) {
// JDBC stuff
}
public void saveData( Object toSave ) {
// JDBC stuff
}
public void deleteData( Object toDelete ){
// JDBC stuff
}
public void updateData( Object toUpdate ){
// JDBC stuff
}
}
И, наконец, вам просто нужно делегировать вызовы.
Позже:
public YouProblematicClass { // not longer that problematic
PersistamceManager persistance = // initialize with the right one.
public void fetchData( Object criteria ) {
// remove the switch and replace it with:
this.persistance.fetchData( criteria );
}
public void saveData( Object toSave ) {
// switch removed
this.persistance.saveData( toSave );
}
public void deleteData( Object toDelete ){
this.persistance.deleteData( toDelete );
}
public void updateData( Object toUpdate ){
this.persistance.updateData( toUpdate );
}
}
Итак, вам просто нужно создать правильный экземпляр для менеджера постоянства в соответствии с типом только один раз. Тогда все вызовы разрешаются полиморфизмом. Это одна из ключевых особенностей объектно-ориентированной технологии.
Если вы решите, что вам нужен еще один диспетчер персистентности, вы просто создаете новую реализацию и назначаете классу.
public WavePersistance implements PersistanceManager {
public void fetchData( Object criteria ) {
// ....
}
public void saveData( Object toSave ) {
// ....
}
public void deleteData( Object toDelete ){
// ....
}
public void updateData( Object toUpdate ){
// ....
}
}