这个设计模式有名字吗? (具有仅调用构造函数的实现的基类)

时间:2016-08-22 13:23:50

标签: java oop inheritance design-patterns nomenclature

编辑:我意识到这种模式与currying非常相似,这是一种功能程序员在调用之前用来指定函数参数的技术。这里的区别在于我们在对象上讨论构造函数而不是简单地使用函数。

在整个几个项目中,我发现自己使用了这个奇怪的设计模式,我找不到它的名字。它有名字吗?也许这只是不好的做法,你告诉我。

设计模式

使用这种模式,你会......

  1. 抽象基类没有抽象方法(我们稍后可以讨论)。
  2. 基类的许多“实现”。但是,这些实现仅用于调用基类的构造函数
  3. Java示例(假设场景)

    我将定义假设情景以提供一些背景信息。

    情境:

    Bob正在编写一个用于扫描源代码的小API。他希望能够检查注释是否在源代码中的给定索引处开始/结束。

    这是鲍勃的代码。

    1。抽象基类

    public abstract class CommentDetector {
    
        private final String startPattern;
        private final String endPattern;
    
        protected CommentDetector(String startPattern, String endPattern) {
            this.startPattern = startPattern;
            this.endPattern = endPattern;
        }
    
        public boolean commentStartsAt(int index, String sourceCode) {
            // ...
        }
    
        public boolean commentEndsAt(int index, String sourceCode) {
            // ...
        }
    
    }
    

    您可能想知道为什么它是抽象的但没有抽象方法。这只是因为Bob 不希望您直接实例化。 Bob希望您编写CommentDetector的实现,然后实例化 。以下是Bob的两个实现......

    2。一些实现

    用于Java中的多行注释:

    public class JavaMultiLineCommentDetector extends CommentDetector {
    
        public JavaMultiLineCommentDetector() {
            super("/*", "*/");
        }
    }
    

    一个用于Java中的单行注释:

    public class JavaSingleLineCommentDetector extends CommentDetector {
    
        public JavaSingleLineCommentDetector() {
            super("//", "\n");
        }
    }
    

    Bob为我们编写了这些实现,以便我们可以编写new JavaMultiLineCommentDetector()而不是new CommentDetector("/*", "*/")

    如果需要,Bob还鼓励您为其他语言编写自己的实现。

    摘要

    • 感觉就像这个设计模式的目的是通过预先定义构造函数调用来提高代码的可读性。

    • 此设计模式为代码提供了多态感(即使它可能/可能不是真正的多态)。

    • 编写新的实现快速而简单。

    • 实现不依赖于彼此,可以独立编译/部署。

    此设计模式是否有名称?

3 个答案:

答案 0 :(得分:1)

  

感觉这个设计模式的目的是通过预定义构造函数调用来提高代码的可读性。

在OOP中,构造函数不应该用于定义契约,因为:

  • 它不如抽象方法精确
  • 具体类可能会滥用超级构造函数
  • 它不是为OOP方式扩展而设计的,因为它不允许覆盖行为。

通常,当您希望允许类客户端选择在处理中必须使用的对象时,更常使用Factory方法或构建器设计模式:

抽象类:

public abstract class CommentDetector {

  private final String startPattern;
  private final String endPattern;

  public abstract String getStartPattern();
  public abstract String getEndPattern();

  public boolean commentStartsAt(int index, String sourceCode){        
      getStartPattern()...
  }

  public boolean commentEndsAt(int index, String sourceCode){
      getEndPattern()....
}

具体类

public class JavaSingleLineCommentDetector extends CommentDetector {

     public String getStartPattern(){
         return "//";
     }

     public abstract String getEndPattern(){
         return "\n";
     }
}
  

这种设计模式给代码带来了多态感(尽管如此   它可能/可能不是真正的多态)。

     

编写新的实现是   快捷方便。

在这种情况下确实如此,因为类变得可扩展。如果需要,可以使用具体类并覆盖任何工厂方法。

答案 1 :(得分:1)

使用可扩展枚举模式(已在注释中注明),您还可以避免继承:

public interface CommentDelimiter {
    String getStartPattern();
    String getEndPattern();
}

public interface CommentDetector {
    boolean commentStartsAt(int index, String sourceCode);
    boolean commentEndsAt(int index, String sourceCode);
}

public enum CommentDetectors implements CommentDetector {
    JAVA_MULTILINE(CommentDelimiters.JAVA_MULTILINE),
    JAVA_SINGLELINE(CommentDelimiters.JAVA_SINGLELINE);

    // ... store commentDelimiter

    public boolean commentStartsAt(int index, String sourceCode) {
        // ... using commentDelimiter.getStartPattern()
    }

    public boolean commentEndsAt(int index, String sourceCode) {
        // ... using commentDelimiter.getEndPattern()
    }
}

public enum CommentDelimiters implements CommentDelimiter {
    JAVA_MULTILINE("/*", "*/"),
    JAVA_SINGLELINE("//", "\n");

    // ... store start, end
}

答案 2 :(得分:0)

Factory Method模式有什么问题?

public class CommentDetector {
    //...

    private CommentDetector(String startPattern, String endPattern) {
        this.startPattern = startPattern;
        this.endPattern = endPattern;
    }

    public static CommentDetector giveMeThisInstance() {
        return new CommentDetector("//", "\n");
    }
    public static CommentDetector giveMeThatInstance() {
        return new CommentDetector("/*", "*/");
    }    
}

此方法将保存您的permgen内存。而且我的主观观点更加一致:将所有内容保持为单个类,但创建具有不同属性的对象。