我正在用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.
}
我觉得这样做真是太糟糕了,但我找不到另一种更清洁的方法。
所以,我想要的是如何让它变得更好。
谢谢,抱歉我的英语不好。
答案 0 :(得分:0)
在编辑后看起来对我说话(假设你遗漏了Exception投掷部分以便于阅读):)
这三种方法都需要在现实案例中引发异常。
答案 1 :(得分:0)
超类由子类继承。你可以在超类中编写你想要共同的方法并保持不变。对于您希望它被子类覆盖的代码的其他部分,在超类中定义其他方法集。在子类中也写入方法。当你从子类调用方法时你可以调用超类方法的
总之,你必须在子类中编写方法来重写超类的方法。
答案 2 :(得分:0)
我还要确保你的超类实际上是抽象的。在这个片段中它不是。总的来说,看起来不错。
还要考虑在超类中声明任何扩展它的类都需要的实例变量。
答案 3 :(得分:0)
首先,在抽象(基类)类中要求子类的实现没有任何问题。这只是一些不应该被滥用的东西,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) { /* ... */ }
}
或类似的东西。
答案 4 :(得分:0)
你的方法很好。坚持好友。
我觉得你理解它的'哲学需要'。只要基类是抽象的,基类“依赖”子类就可以了。它知道此时必须注册一些东西,但它没有关于究竟要注册什么的最微弱的线索。因此,高级进程在基类中编码,其中“孔”可以由派生类插入。高级过程和“漏洞”本身的位置是有价值的,这证明了基类的实现是正确的。派生类只遵循“按差异编码”的基本OO原则并插入“漏洞”。
答案 5 :(得分:0)
您的方法很好,但是需要对其进行简单的改进以使其完美-使startRMI()
方法final
:
public final void startRMI(int port) {
fillRegistry();
}
这样,您可以防止某人重写它(可能是因为不知道startRMI()
中的所有内容都应被重用,并且仅fillRegistry()
必须自定义)。
您的解决方案通常与template method design pattern相匹配:
模板方法是超类中的方法,通常是抽象的 父类,并根据 高级步骤数。这些步骤本身是由 与模板方法在同一类中的其他辅助方法。
在这种情况下,辅助方法可以是抽象方法 需要子类来提供具体的实现或挂钩 方法,在超类中具有空的主体。 子类可以 (但不是必须)通过覆盖 挂钩方法。模板方法的目的是定义 操作的整体结构,同时允许子类 完善或重新定义某些步骤。 (维基百科)
鉴于上述情况,方法startRMI()
是一种模板方法,它通过使用许多高级步骤来定义操作的框架(在您的情况下,这只是一个步骤,但这没有什么区别)。您示例中的方法fillRegistry()
是一个高级步骤-在超类中被定义为抽象方法,并且在超类中具有具体的实现。
另一方面,如果您要在子类中覆盖方法startRMI()
,将不再可行。这就是为什么您应该将其设置为final
以避免混淆-这样,创建子类的人将知道他必须实现fillRegistry()
(因为它是抽象的),但不应更改startRMI
的实现(因为它是最终的)。
因为这是一种常用的设计模式,所以我完全不担心这种解决方案是否可行,很多人正在这样做,并且知道设计模式的每个人都会意识到这一点,我认为这很自然甚至对于不了解设计模式的开发人员。