在两个类之间共享代码(使用抽象操作)

发布于 2024-10-20 09:23:46 字数 898 浏览 1 评论 0原文

我正在用 Java 开发一个服务器应用程序。服务器需要两种类型的服务器类。这些类有一些共同的方法,这些方法中的代码是完全相同的。因此,我创建了一个包含所有共享代码的抽象超类,并且两个类都继承了它。但是,代码的某些部分需要通过子类来精确化。我的意思是超类“依赖”子类方法。

这是我的意思的一个纯粹的例子:

public abstract class AbstractServer
{
    public void loadConfig(String configPath)
    {
        //Load the configuration file.

        //This code is exactly the same for subclasses.
    }

    public void startRMI(int port)
    {
        //Create an empty RMI registry.
        //This part also need to be identical.

        //Here' where the superclass "rely" on subclasses.
        fillRegistry(); //Call the method overwritten by subclasses.
    }

    /**
    Bind remote objects in the RMI registry
    */
    protected abstract void fillRegistry(); //This method will be overriten by subclasses.
}

我觉得这样做真的很糟糕,但我找不到另一种更干净的方法来做到这一点。

所以,我想要的是一些关于如何让它变得更好的建议。

谢谢,抱歉我的英语不好。

I'm developping a server application in Java. The server need two type of server classes. These classes have some methods in common, the code in these methods is exactly the same. So i create an abstract super-class containing all the shared code, and both classes are inheriting it. But, there is some part of the code that need to be precised by subclasses. I mean that the superclass "rely" on subclasses methods.

Here is a purified example of what i mean:

public abstract class AbstractServer
{
    public void loadConfig(String configPath)
    {
        //Load the configuration file.

        //This code is exactly the same for subclasses.
    }

    public void startRMI(int port)
    {
        //Create an empty RMI registry.
        //This part also need to be identical.

        //Here' where the superclass "rely" on subclasses.
        fillRegistry(); //Call the method overwritten by subclasses.
    }

    /**
    Bind remote objects in the RMI registry
    */
    protected abstract void fillRegistry(); //This method will be overriten by subclasses.
}

I feel that it's really bad to make it like that, but i can't find another cleaner way to do it.

So, what i want is some advice on how i could make it better.

Thanks, and sorry for my bad english.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

遗心遗梦遗幸福 2024-10-27 09:23:46

你的方法很好。坚持下去,伙计。

我感觉到你理解它的“哲学需要”。只要基类是抽象的,基类“依赖”子类就可以。它知道此时必须注册一些东西,但对于到底要注册什么,它没有任何线索。因此,高级过程在基类中进行编码,并带有可以由派生类插入的“漏洞”。高层流程和“洞”本身的位置是有价值的,这证明了基类的实现是合理的。派生类只是遵循“差异编码”的基本面向对象原则并堵塞“漏洞”。

Your approach is just fine. Stick with it buddy.

I feel your 'philosophical need' to understand it. Base class 'relying' on the subclass is fine as long as the base class is abstract. It knows that some things have to be registered at this point, but it doesn't have the faintest clue about what exactly to be registered. So the high-level process is encoded in the base class with 'holes' that can be plugged in by the derived class. The high level process and the position of the 'hole' itself is valuable and this justifies the implementation of the base class. The derived classes just follow the fundamental OO principle of 'coding by difference' and plugs the 'holes'.

阳光下慵懒的猫 2024-10-27 09:23:46

在您编辑后,对我来说看起来很正确(假设您为了可读性而省略了异常抛出部分):)

所有三种方法都需要在现实情况下引发异常。

Looks about right to me after your edits (assuming that you left out the Exception throwing part for readability) :)

All three methods would need to raise exceptions in a real world case.

浮世清欢 2024-10-27 09:23:46

超类被子类继承。您可以在超类中编写您想要通用的方法并保持不变。对于希望被子类覆盖的代码的其他部分,请在超类中定义其他方法集。也在子类中编写方法。当你从子类调用方法时,你可以调用超类的方法,

简而言之,你必须在子类中编写方法来覆盖超类的方法。

Super class is inherited by sub-class. You can write methods in super class which you want to make common and leave it untouched. For the other part of code which you want it to be overwritten by sub classes define other set of methods in super class. write methods in sub-classes also. when u call method from sub-class u can put to call super-class method's

in short u have to write methods in sub class to over write the methods of superclass.

年华零落成诗 2024-10-27 09:23:46

我还要确保你的超类实际上是抽象的。在这个片段中它不是。不过总体来说,看起来还不错。

还要考虑在超类中声明扩展它的类也需要的任何实例变量。

I would also make sure that your superclass is actually abstract. In this snippet it isn't. Overall though, looks decent.

Also consider declaring any instance variables in your superclass that classes that extend it will need as well.

嘿哥们儿 2024-10-27 09:23:46

首先,要求子类在抽象(基)类中实现并没有什么问题。 IMO,这只是不应该被滥用的东西。然而,如果我必须避免它,我会让 ServerClass 根本不抽象,并定义它的每个方法。相反,我会创建RegistryFactory类并将它们传递给ServerClass:

class ServerClass {
   public void startRMI(int port, RegistryFactory rf) {
      // ...
      rf.fillRegistry(this);
   }
}


interface RegistryFactory {
   /**
    * Implement this method
    */
   public void fillRegistry(ServerClass server);
}

public class RMIRegistryFactory implements RegistryFactory {
   public void fillRegistry(ServerClass server) { /* ... */ }
}

或者类似的东西。

First, there is nothing wrong with requiring subclasses' implementation in abstract (base) classes. It's just something that should not get abused, IMO. However, if I had to avoid it, I would make the ServerClass not abstract at all, and define every method of it. Instead, I would create RegistryFactory classes and pass them to the ServerClass :

class ServerClass {
   public void startRMI(int port, RegistryFactory rf) {
      // ...
      rf.fillRegistry(this);
   }
}


interface RegistryFactory {
   /**
    * Implement this method
    */
   public void fillRegistry(ServerClass server);
}

public class RMIRegistryFactory implements RegistryFactory {
   public void fillRegistry(ServerClass server) { /* ... */ }
}

Or something like that.

何以笙箫默 2024-10-27 09:23:46

您的方法很好,但需要一个简单的改进才能使其完美 - 将 startRMI() 方法设为 final

public final void startRMI(int port) {
    fillRegistry();
}

这样您就可以防止有人覆盖它(可能是因为不知道 startRMI() 中的所有内容都应该重用,并且只有 fillRegistry() 需要定制)。

您的解决方案通常符合模板方法设计模式

模板方法是超类中的方法,通常是抽象方法
超类,并根据 a 定义操作的骨架
高级步骤的数量。这些步骤本身是由
与模板方法位于同一类中的其他辅助方法。

辅助方法可以是抽象方法,在这种情况下
需要子类提供具体的实现,或者hook
方法,其超类中具有空主体。 子类可以
(但不是必需的)通过覆盖来自定义操作
钩子方法。模板方法的目的是定义
操作的整体结构,同时允许子类
完善或重新定义某些步骤
。 (维基百科)

鉴于上述情况,方法 startRMI() 是一种模板方法,它通过使用许多高级步骤来定义操作的骨架(在您的情况下,它只有一个步骤,但这并不没有什么区别)。示例中的方法 fillRegistry() 是一个高级步骤 - 它在超类中定义为抽象方法,并在超类中具有具体实现。

另一方面,如果您要在子类中重写方法 startRMI(),那么这就不再可行了。这就是为什么你应该将其设为 final 以避免混淆 - 这样创建子类的人就会知道他必须实现 fillRegistry() (因为它是抽象的),但不应更改startRMI 的实现(因为它是最终的)。

由于这是一种常用的设计模式,所以我完全不用担心这个解决方案是否可以,很多人都在这样做,每个了解设计模式的人都会认识到它,我认为即使对于开发人员来说也感觉很自然谁不知道设计模式。

Your approach is fine, but it needs a simple improvement to make it perfect - make the startRMI() method final:

public final void startRMI(int port) {
    fillRegistry();
}

This way you will prevent that someone overrides it (maybe because of not knowing that everything in startRMI() should be reused and that only fillRegistry() has to be customized).

Your solution generally matches the template method design pattern:

The template method is a method in a superclass, usually an abstract
superclass, and defines the skeleton of an operation in terms of a
number of high-level steps. These steps are themselves implemented by
additional helper methods in the same class as the template method.

The helper methods may be either abstract methods, for which case
subclasses are required to provide concrete implementations, or hook
methods, which have empty bodies in the superclass. Subclasses can
(but are not required to) customize the operation by overriding the
hook method
s. The intent of the template method is to define the
overall structure of the operation, while allowing subclasses to
refine, or redefine, certain steps
. (Wikipedia)

Given the above, the method startRMI() is a template method which defines the skeleton of an operation by using a number of high-level steps (in your case it's only one step but this doesn't make a difference). The method fillRegistry() in your example is a high-level step - it's defined as an abstract method in the superclass and has a concrete implementation in the superclasses.

On the other side, if you would override the method startRMI() in a subclass, this would not be OK anymore. That's why you should make it final to avoid confusion - this way someone who creates a subclass will know that he must implement fillRegistry() (since it's abstract) but should not change the implementation of startRMI (since it's final).

Since this is a commonly used design pattern, I wouldn't worry at all if this solution is OK, a lot of people are doing it like that and everyone who knows design patterns will recognize it, I think it feels very natural even for developers who don't know the design pattern.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文