Design patterns are a classic way to solve recurring software design problems.
In this article, we’ll revisit the Adapter pattern, but written in Clprolf — a language that makes object-oriented roles and contracts explicit.
Even if you don’t know Clprolf yet, don’t worry:
- the use case is familiar,
- the solution is the same pattern you already know,
- and you’ll see how Clprolf makes both sides clearer.
🤔 The Problem
Imagine you have an existing class that implements an old interface, but your application now expects the modern version of that interface.
- You cannot change the old class (it’s legacy code, or external).
- You need a way to reuse it, but expose it through the newer contract.
That’s where the Adapter comes in.
✅ The Clprolf Solution
In Clprolf, the rule is simple:
- A concrete agent can contract only one
version_inh
. - So you cannot make the same class both an “old” and a “modern” implementation.
- Instead, you create a new agent — the Adapter — which contracts the modern version, and internally uses the old one via
with_compat
.
📝 Example: Enumeration → Iterator
Old Java APIs used Enumeration
, but modern code expects Iterator
. We want to reuse existing Enumeration
implementations without rewriting them.
Clprolf Code
// 1. Old contract (an abstraction)
public version_inh abstraction Enumeration<E> {
boolean hasMoreElements();
E nextElement();
}
// 2. Modern contract (an agent)
public version_inh agent Iterator<E> {
boolean hasNext();
E next();
}
// 3. Adapter agent: contracts the modern version
public agent EnumToIterAdapter<E> contracts Iterator<E> {
private with_compat Enumeration<E> enumeration;
public EnumToIterAdapter(with_compat Enumeration<E> enumeration) {
this.enumeration = enumeration;
}
public boolean hasNext() {
return enumeration.hasMoreElements();
}
public E next() {
return enumeration.nextElement();
}
}
🔎 Why this is clear in Clprolf
-
version_inh
makes it explicit: these are role contracts meant to be implemented by agents. -
contracts
shows clearly: the Adapter is a modernIterator
. -
with_compat
highlights the dependency on the oldEnumeration
. - No hidden tricks: we see immediately that the Adapter is a new agent created for translation.
And here’s an important detail:
-
Enumeration
is an abstraction (a very minimal contract, part of theagent
declension in Clprolf). -
Iterator
is a full agent, representing the modern iteration model. - So the Adapter not only bridges old to new, but also shows a shift in philosophy: from abstraction to agent.
🎯 Key takeaway
In Clprolf, the Adapter is never a “magical disguise.”
It’s simply:
A new agent that contracts the modern interface, and delegates to an old implementation through
with_compat
.
This removes confusion and makes the intent crystal clear.
👀 Bonus: Using the Adapter in a Demo
For completeness, here’s how a client would actually use the Adapter.
Even if the old API gives you an Enumeration
, the Adapter lets you treat it as a modern Iterator
:
public worker_agent AdapterDemo {
public static void main(String[] args) {
Vector<String> legacyVector = new Vector<>();
legacyVector.add("one");
legacyVector.add("two");
with_compat Enumeration<String> enumeration = legacyVector.elements();
with_compat Iterator<String> iterator = new EnumToIterAdapter<>(enumeration);
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
✨ What do you think? Have you used the Adapter pattern in real projects (e.g., bridging old APIs with modern ones)?
Top comments (0)