技术问询:以接口实现抽象工厂模式——Java 8默认方法能否替代抽象类?
Great question—Java 8's default methods definitely blurred the lines between interfaces and abstract classes for design patterns like Abstract Factory. Let's break this down clearly.
Can we use interfaces instead of abstract classes for Abstract Factory?
Absolutely. With default methods, you can define default implementations for factory methods directly in an interface, which lets concrete factory classes implement the interface and only override the methods they need to customize. Here's a quick example:
// Abstract Factory Interface with default methods interface AbstractFactory { default Product createProductA() { return new DefaultProductA(); } default Product createProductB() { return new DefaultProductB(); } } // Concrete Factory class ConcreteFactory1 implements AbstractFactory { // Override only the method we need to change @Override public Product createProductA() { return customProductA(); } }
This works perfectly for many basic Abstract Factory use cases where you don't need shared state or complex initialization logic.
Scenarios where traditional abstract class-based factories are better (beyond non-static/non-final fields)
While interfaces are viable now, abstract classes still shine in several key scenarios:
Shared mutable state management: Suppose you want to track how many instances a factory has created, or cache some reusable resources. An abstract class can have a
protected int instanceCountfield that all concrete factories inherit and update. Interfaces can't hold mutable state—any fields you add are implicitlypublic static final, so you can't track per-factory state.Reusable constructor initialization logic: Abstract classes can have constructors to handle common setup, like loading configuration files, establishing database connections, or validating factory parameters. Concrete factories just call
super(...)to reuse this logic. Interfaces have no constructors, so you'd have to duplicate this setup code in every concrete factory, or hack around it with static initializers (which are less flexible and can't take parameters).Clean hierarchical abstraction: If you need to build a layered factory structure (e.g.,
BaseFactory→VehicleFactory→ElectricVehicleFactory), abstract classes make this seamless. You can add incrementally more specific default logic in each layer without forcing subclasses to reimplement everything. With interfaces, multiple inheritance can lead to default method conflicts (if two parent interfaces have the same default method signature), forcing you to resolve conflicts in every implementing class—this gets messy fast with deep hierarchies.Fine-grained access control: Abstract classes let you mark helper methods or state as
protected, so only subclasses can access them. Interfaces' default methods are alwayspublic, meaning any helper logic you put in an interface is exposed to the entire codebase. If you have internal factory logic that shouldn't be public, abstract classes are the way to go.Backward compatibility with legacy code: If your project already has a codebase built around abstract class factories, sticking with abstract classes avoids costly refactoring. Legacy code might rely on abstract class-specific features (like constructor chaining or protected state) that would require sweeping changes to migrate to interfaces.
内容的提问来源于stack exchange,提问作者minizibi

