Лучший способ избежать дублирования кода, если два класса, расширяющие разные классы
Я работаю над проектом 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();
}