2016-02-16 7 views
-1

У меня возникла проблема, которая для меня новая. В принципе, кто-то уже написал класс A. Важные части выглядит как этотРефакторинг и предотвращение дублирования кода

class A{ 

// some instance variables 

public A(){ 
    // Calls methods 
    build(); 
    // Calls more methods 
} 

private build(){ 
    item = makeItem(); 
    anotherItem = makeAnotherItem(); 
    // more code 
} 

private makeItem(){ 
    // Does some things and calls updateItem() 
} 

private updateItem(){ 
    // Does some things with instance variables of class A 
    // and calls yet another method in class A. 
} 

Моя проблема заключается в том, что сборка() делает именно то, что мне нужно, но мне это нужно в другом классе. Теперь вот проблемы:

  1. класс А делает намного больше, чем то, что я написал, и поэтому я не могу создать его объект. Это было бы бессмысленно.
  2. Я пробовал копировать метод build() для моего класса B. Однако build() использует другие методы. И поэтому я должен их скопировать и, конечно, они называют другие методы и используют переменные экземпляра, объявленные другими способами. В принципе, мне пришлось бы копировать 200 строк кода.

Я предполагаю, что эта проблема на самом деле имеет имя, но я не знаю, что она называется, и поэтому искала только некоторые основные термины. Что я могу сделать, чтобы использовать build() в моем классе B?

+0

Сделайте это 'public', удалите ненужные методы, создайте экземпляр' A' и используйте 'build()'. Или, если состояние не важно, сделайте его «статическим» классом и используйте 'build()' напрямую. – Maroun

+1

Первый подход: Извлечь общий код в отдельный абстрактный класс AbstractA, сделать A и B расширением AbstractA. Второй подход: извлечь общий код в конкретном классе C и использовать C в качестве делегата в A и B.Могут быть другие решения, но невозможно помочь вам больше без конкретного кода. –

+0

«класс А делает намного больше, чем то, что я написал» - убедитесь, что это имеет смысл, прежде чем спускаться по кроличьей дыре. Помимо этого вы можете смотреть на шаблон «Builder». – ChiefTwoPencils

ответ

2

Вы используете код метода построения в двух классах, но наследование не полезно? Затем вы можете повторно использовать код метода построения с композицией. (подсказка Favor Composition over Inheritance) Создайте новый класс C, который содержит метод сборки. Класс C используется классами A и B через композицию. Они делегируют метод сборки класса C.

См. Метод рефакторинга Мартина Фаулера.

https://sourcemaking.com/refactoring/smells/duplicate-code также см https://sourcemaking.com/refactoring/replace-inheritance-with-delegation

0

Всегда рефакторинг небольшими шагами. например Поместите вещи вместе, которые принадлежат вместе, возможно, существует необходимость для другого класса C, который содержит makeItem, makeAnotherItem и соответствующие переменные экземпляра. Нет общего ответа, и это зависит от того, как ваш код выглядит точно

0

первую очередь если построить() в классе А с помощью других частных методов А, что пахнет, как вы будете нуждаться в сам класс А.

Одним из вариантов может быть создание абстрактного класса, содержащих общие методы (включая метод сборки), и расширить этот абстрактный класс, класс А и В. таким образом, вы не будете иметь повторяющийся код

Если по каким-то причинам вы не хотите, чтобы прикоснуться к классу а, я предлагаю вам создать интерфейс, как:

public interface Builder{ 
    void build() 
} 

, а затем реализовать этот интерфейс с помощью вашего класса B, а также расширить класс а, так что у вас есть реализация метода сборки.

public class B extends A implements Builder{ 
    // build() of class A will be used 
    // do other staff 
} 

При этом, нет никаких изменений в классе А вообще (это может быть желательно, если это унаследованный код или что-то) + Builder может быть использован в качестве типа в API вы хотите выставить.