Лучший способ избежать дублирования кода, если два класса, расширяющие разные классы

Я работаю над проектом Android, и я столкнулся с этой ситуацией.

У меня есть класс 2:

class A extends B
{

openDoor(){
//impl
}

closeDoor(){
//impl
}

}

class X extends Y{

openDoor(){
//impl
}

closeDoor(){
//impl
}

}

Теперь, если вы заметили, что два метода являются общими для обоих классов openDoor() и closeDoor()

Каков наилучший способ избежать дублирования методов?

Мой подход

class ContainingDuplicateMethods{

     openDoor(){
    //impl
    }

    closeDoor(){
    //impl
    }

    }
   }

Создайте объект ContainingDuplicateMethods в обоих классах и вызовите методы, которые мы называем Strategy Pattern, но это лучшее решение? почему, поскольку в крупных проектах мы не можем следовать этому подходу, и люди говорят, что это не ХОРОШАЯ ПРАКТИКА, в таком случае, какой подход мне нужно соблюдать?

Обратите внимание, что class A and X уже расширяют другие классы, а также я не хочу использовать static, потому что - статические члены загружаются в память при запуске программы и будут находиться в памяти до тех пор, пока программа не будет завершена, скажем, мой код запускается непрерывно в течение нескольких дней или недель и продолжает создавать множество объектов, используя статические ссылки, поэтому может возникнуть вероятность того, что у нас может закончиться нехватка памяти.

Ответ 1

"Использовать композицию над наследованием" - это полезная вещь, которую нужно запомнить.

У вас есть класс Door с открытым и закрытым. Включите Door как член как A, так и B.

Воила, работа выполнена.

Итак A.getDoor().close(). B.getDoor().open() и т.д.

Если вам нужен общий интерфейс для A и B (так что вы можете использовать любой из них), создайте

interface HasDoor {
    Door getDoor();
}

Теперь A и B могут расширить любой класс, который вам нравится, и реализовать HasDoor. Любой класс, требующий двери, может принять HasDoor (или просто принять объект Door) и вызвать open, close и т.д.

Нет дублированного кода, полная гибкость.

Если вам нужны методы Door для вызова методов в A и B, тогда создайте класс Door как абстрактный и реализуйте его в A и B как анонимный внутренний класс. Абстрактные методы будут вызываться из Door, а затем вы можете сделать любую обработку в A и B при вызове этих методов.

Например, класс A становится:

 class A implements HasDoor {
      private Door door = new Door() {
          @override void notifyDoorChanged(boolean closed) {
                // The door is telling us its been opened or closed
          }
      }

      @override
      public Door getDoor() {
           return door;
      }
 }

Где дверь:

 public abstract class Door {
      boolean closed;
      abstract notifyDoorChanged();

      public void close() {
         closed = true;
         notifyDoorChanged(closed);
      }

      // etc
 }

Обратите внимание, что это похоже на шаблон стратегии - но это не совсем то же самое. Шаблон стратегии имеет один главный объект, а затем вы включаете несколько стратегий (т.е. Разные формы двери). У этого есть одна Дверь и несколько других объектов, использующих тот же тип Дверь, хотя вы могли бы расширить его, чтобы использовать шаблон Стратегии и иметь множество вариантов дверей очень легко.

Ответ 2

Это реализация ответа, опубликованного Тимом Б. Это очень гибкий подход. Он следует принципам объектно-ориентированного повторного использования:

  • Определите, что меняется и отделяет их от того, что остается тем же.
  • Программа для интерфейса, а не для реализации.
  • Использовать композицию объекта над наследованием.

    public class Main {

        public static void main(String[] args) {
            X x = new X();
            A a = new A();
            x.getDoor().open();
            x.getDoor().close();
            a.getDoor().open();
            a.getDoor().close();
        }
    }
    
    
    interface HasDoor {
        Door getDoor();
    }
    
    interface Door {
        public void open();
        public void close();
    }
    
    class A extends B implements HasDoor {
    Door d;
    
    @Override
    public Door getDoor() {
        Door door = new Door() {
            public void open() {
                System.out.println("Open A Door");
            }
    
            public void close() {
                System.out.println("Close A Door");
            }
        };
        return door;
    }
    

    }

    класс X расширяет Y реализует HasDoor {   Дверь d;

    @Override
    public Door getDoor() {
        Door door = new Door() {
            public void open() {
                System.out.println("Open X Door");
            }
    
            public void close() {
                System.out.println("Close X Door");
            }
        };
        return door;
    }
    

    }

    класс B {} класс Y {}

Если вы не хотите использовать интерфейс HasDoor, вы можете объявить конструкторы внутри класса X и класса A, который инициализирует экземпляр Door.

Пример;

class X extends Y {
    Door d;
     public X() {
         d = new Door() {
            public void open() {
                System.out.println("Open X Door");
            }

            public void close() {
                System.out.println("Close X Door");
            }
        };

     }



}

Ответ 3

так что ваш класс a и класс a должны следовать тем же функциям. то есть оба класса имеют одинаковые функции.

поскольку классы уже расширили другой класс, мы можем использовать интерфейс

interface door
{
 openDoor(){
    }

    closeDoor(){
    }


}

оба класса a и x могут реализовать интерфейс двери. enter image description here

Класс может реализовывать любое количество интерфейсов, но может распространять только один класс.

Если реализация двери класса такая же, мы можем сделать это

class Door
{
openDoor(){
impl//
    }

    closeDoor(){
impl//
    }


}
class A extends b
{
Door d=new Door();
d.opendoor();
d.closeDorr();


}

Ответ 4

Да, создайте абстрактный класс, который содержит общий код. Попросите этот абстрактный класс реализовать интерфейс, содержащий необходимые методы.

Пусть оба класса расширяют абстрактный класс.

Ответ 5

Я думаю, вам следует создать интерфейс с методами openDoor() и closeDoor(). После этого наследуют классы A и X от этого интерфейса и реализуют методы. Если реализация методов аналогична, вы можете создать класс утилиты со статическими методами.

Ответ 6

public interface YourInterface{
  public void openDoor();
  public void closeDoor();
}

public abstract class YourAbstractClass implements YourInterface{
  public abstract void openDoor();
  public abstract void closeDoor();
}

public class YourClass extends YourAbstractClass{
  @Override
  public void openDoor();
  public void closeDoor();
}

public class YourSubClass extends YourClass{
  //you can just call super methods here
  super.openDoor();
  super.closeDoor();
}