在面向对象编程中,我们经常遇到需要基类提供通用行为,而派生类在此基础上实现特定逻辑的场景。然而,当涉及到静态成员和静态方法时,多态的常规机制并不能直接适用。
考虑以下初始代码结构:
class Base {
Base() {
System.out.println("Base Constructor");
}
}
class Derived1 extends Base {
private static String pattern = "a+b+"; // 派生类特有的静态模式
Derived1() {
super();
System.out.println("Derived 1 Constructor");
}
public static boolean doesMatch(String v) { // 重复的匹配方法
return v.matches(pattern);
}
}
class Derived2 extends Base {
private static String pattern = "c+"; // 派生类特有的静态模式
Derived2() {
super();
System.out.println("Derived 2 Constructor");
}
public static boolean doesMatch(String v) { // 重复的匹配方法
return v.matches(pattern);
}
}
class Builder {
public static Base baseFromString(String v) throws Exception {
if (Derived1.doesMatch(v)) return new Derived1(); // 硬编码的条件判断
if (Derived2.doesMatch(v)) return new Derived2();
throw new Exception("Could not match " + v + " to any derived type.");
}
}
class Test {
public static void main(String[] args) throws Exception {
Base b = Builder.baseFromString("aaab"); // 测试
}
}这段代码存在两个主要问题:
为了解决上述问题,我们可以采用一种结合工厂模式和注册机制的策略。核心思想是将匹配逻辑和对象创建过程从具体的派生类中解耦出来,并由一个中心化的 Builder 来管理。
首先,我们将派生类中的 pattern 静态成员和 doesMatch 静态方法移除,让它们只关注自身的构造逻辑。
class Base {
Base() {
System.out.println("Base Constructor");
}
}
class Derived1 extends Base {
Derived1() {
super();
System.out.println("Derived 1 Constructor");
}
}
class Derived2 extends Base {
Derived2() {
super();
System.out.println("Derived 2 Constructor");
}
}为了实现动态创建不同派生类实例的能力,我们定义一个简单的工厂接口 NewBase。这个接口只有一个 create() 方法,用于返回一个 Base 类型的实例。
interface NewBase {
Base create();
}在Java 8及更高版本中,我们也可以直接使用标准库提供的 java.util.function.Supplier
接下来,我们创建一个 Pattern 类,它将正则表达式字符串和对应的 NewBase 工厂封装在一起。这样,每个 Pattern 对象就代表了一种“匹配规则”和“匹配成功后的创建行为”。
final class Pattern {
final private String pattern;
final private NewBase newBase;
public Pattern(String pattern, NewBase newBase) {
this.pattern = pattern;
this.newBase = newBase;
}
public String getPattern() {
return pattern;
}
public NewBase getNewBase() {
return newBase;
}
}现在,我们重构 Builder 类。它将不再直接依赖于具体的 Derived 类,而是维护一个 Pattern 对象的列表。
import java.util.ArrayList;
import java.util.List;
class Builder {
final private static List newObjects = new ArrayList<>();
// 注册方法
private static void addPattern(String pattern, NewBase newObject) {
newObjects.add(new Pattern(pattern, newObject));
}
// 静态初始化块,用于注册所有派生类及其匹配模式
static {
addPattern("a+b+", Derived1::new); // 使用方法引用注册Derived1的工厂
addPattern("c+", Derived2::new); // 使用方法引用注册Derived2的工厂
}
// 动态构建方法
public static Base baseFromString(String v) throws Exception {
for (Pattern p : newObjects) {
if (v.matches(p.getPattern())) {
return p.getNewBase().create();
}
}
throw new Exception("Could not match " + v + " to any derived type.");
}
}
class Test {
public static void main(String[] args) throws Exception {
System.out.println("Matching 'aaab':");
Base b1 = Builder.baseFromString("aaab"); // 应该创建 Derived1
System.out.println("Created: " + b1.getClass().getSimpleName());
System.out.println("\nMatching 'ccc':");
Base b2 = Builder.baseFromString("ccc"); // 应该创建 Derived2
System.out.println("Created: " + b2.getClass().getSimpleName());
System.out.println("\nMatching 'xyz' (no match expected):");
try {
Base b3 = Builder.baseFromString("xyz");
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
} 运行结果示例:
Matching 'aaab': Base Constructor Derived 1 Constructor Created: Derived1 Matching 'ccc': Base Constructor Derived 2 Constructor Created: Derived2 Matching 'xyz' (no match expected): Error: Could not match xyz to any derived type.
通过上述重构,我们成功解决了最初的两个问题,并带来了多项优势:
解耦与代码复用:
可扩展性(符合开闭原则):
// 假设新增 Derived3 类
class Derived3 extends Base {
Derived3() {
super();
System.out.println("Derived 3 Constructor");
}
}
// 只需修改 Builder 的静态初始化块
static {
addPattern("a+b+", Derived1::new);
addPattern("c+", Derived2::new);
addPattern("d+", Derived3::new); // 新增注册
}灵活性: 匹配模式(
正则表达式)和对应的对象创建逻辑可以独立配置和管理。这种机制使得系统更加灵活,易于维护和修改。
Java 9+ 方法引用: Derived1::new 这种方法引用语法简洁高效,可以直接作为 NewBase 接口的实现,极大地简化了代码。
通过引入工厂接口、封装匹配模式与工厂对象,并利用 Builder 类的注册机制,我们成功地将Java中派生类的静态值(匹配模式)与共享方法(匹配逻辑)解耦。这种设计模式不仅解决了静态成员多态性的限制,还显著提升了代码的可扩展性和可维护性,是处理类似动态对象创建和匹配场景的有效实践。