Alternative Classes with Different Interfaces

Referenced by patterns
Symptom

Two classes do similar things but with mismatched method names and signatures — sortBy() vs orderUsing(), valueOf() vs evaluate().

Goal

Equivalent operations have equivalent signatures; a shared superclass or interface emerges naturally.

Smellier version

class CSVExporter { writeAll(rows) {} }
class JSONExporter { dump(data) {} }

Fresher version

class CSVExporter implements Exporter { write(rows) {} }
class JSONExporter implements Exporter { write(rows) {} }
Example source: Illustrative example written for this site, not a quotation from any source.
Pressure

Substitution becomes copy-paste; consumers can't treat the two interchangeably; abstraction over them is impossible.

Tradeoff

Aligning the interfaces may force renames across both classes and every consumer; for classes that have stable independent APIs and only superficial similarity, the alignment is invented coherence.

Relief

Polymorphic use becomes possible; new alternatives plug in without bespoke adapters.

Trap

Forcing two classes into a shared interface because they look similar — even when their underlying contracts genuinely differ — creates an abstraction that hides important distinctions.