【问题标题】:Best way to avoid duplicate code if two classes extending different class如果两个类扩展不同的类,避免重复代码的最佳方法
【发布时间】:2013-12-18 06:32:28
【问题描述】:

我正在开发一个 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 对象并调用方法,我们称之为策略模式,但这是最好的解决方案吗?为什么因为在大型项目中我们不能遵循这种方法,人们说这不是好的做法,在这种情况下我需要遵循什么方法?

请注意class A and X 已经在扩展其他类,而且我也不想使用静态,因为 - 静态成员在程序执行开始时被加载到内存中,并且将在内存中直到程序终止,比如我的代码运行连续几天或几周,并继续使用静态引用创建许多对象,因此我们可能会耗尽内存。

【问题讨论】:

  • 1.使用抽象类..把你的常用方法放在那里......其他想要使用这些方法的类可以通过扩展抽象类来实现...... 2.如果你已经在扩展另一个类,你几乎没有选择。 .
  • @TheLostMind 是的,但是我的 A 和 X 班已经在扩展课程了
  • 然后创建一个通用的 utils 类并将这些方法设为静态。您可以通过“UtilsClass.openDoor()”在您的其他类中直接使用这些常用方法,无需继承...
  • @TheLostMind 请看我的编辑
  • 我认为你必须使用使用策略模式。我在这里没有看到任何其他选项...我不是静态方法/字段的忠实粉丝:P

标签: java android code-duplication


【解决方案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
 }

请注意,这类似于策略模式 - 但并不完全相同。策略模式有一个主对象,然后您插入多个策略(即不同形式的门)。这有一个 Door 和多个使用相同类型 Door 的其他对象,尽管您可以将其扩展为使用策略模式并非常轻松地实现多个门。

【讨论】:

    【解决方案2】:

    这是 Tim B 发布的答案的实现。 这是一种非常灵活的方法。它遵循面向对象重用的原则:

    1. 识别变化并将它们与保持不变的部分区分开来。
    2. 编程到接口,而不是实现。
    3. 优先考虑对象组合而不是继承。

      公共类主{

          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's Door");
              }
      
              public void close() {
                  System.out.println("Close A's Door");
              }
          };
          return door;
      }
      

      }

      X 类扩展 Y 实现 HasDoor{ d门;

      @Override
      public Door getDoor() {
          Door door = new Door() {
              public void open() {
                  System.out.println("Open X's Door");
              }
      
              public void close() {
                  System.out.println("Close X's 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's Door");
                }
    
                public void close() {
                    System.out.println("Close X's Door");
                }
            };
    
         }
    
    
    
    }
    

    【讨论】:

    • 在我看来,这种方法仍然存在重复代码根据操作的问题。在 Tim B 的回答中,Door 是一个抽象类,这就是为什么它可以为 open() 和 close() 方法提供具体实现的原因。在您的方法中,门就是接口。这就是为什么 A 类和 X 类仍然必须为 Door 的 open() 和 close() 方法提供具体实现的原因。这两种方法与 op 的问题完全相同。
    【解决方案3】:

    所以在这里你的类 a 和类 a 必须遵循相同的功能。 即两个类具有相同的功能。

    由于类已经扩展了另一个类,我们可以使用接口

    interface door
    {
     openDoor(){
        }
    
        closeDoor(){
        }
    
    
    }
    

    类a和x都可以实现门接口。

    一个类可以实现任意数量的接口,但只能扩展一个类。

    如果类门的实现相同,我们可以这样做

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

    【讨论】:

    • 是的,但是我的 openDoor() closeDoor() 实现也是一样的,所以创建一个接口将再次有重复的实现
    • 如果实现也相同,则将其写入类中。在a和X类中创建门类的对象并访问关闭和打开功能
    • 好的,那么我将在哪里使用这个接口呢?我很困惑,你能详细说明一下吗
    • 那么不需要接口,只需创建一个类门并实现该功能。然后您需要该功能的地方只需创建该类的对象并访问它。在验证的情况下,我们喜欢这将创建一个用于验证的类并在所有其他类中使用该类。
    • 你的意思是创建那个类的对象?
    【解决方案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();
      }
      

      【讨论】:

      • 你的方法很好,但是如果你扩展了一些类,你就不能扩展其他类。但在接口的情况下,您可以实现多个接口。
      • 没关系,因为 mr.user3114009 只是在寻找避免重复方法的方法
      • 我相信YourSubClass Class就是他要找的那个
      猜你喜欢
      • 2022-06-10
      • 1970-01-01
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多