Decouple an abstraction from its implementation so that the two can vary independently.

Abstract method addition to Abstraction and Implementor.

module original {
define abstract class Abstraction {
Implementor imp;
define void operation() { imp.operationImp(); }
}
define class RefinedAbstraction extends Abstraction {
...
}
define abstract class Implementor {
define abstract void operationImp();
}
define class ConcreteImplementorA extends Implementor {
void operationImp() { ... }
}
define class ConcreteImplementorB extends Implementor {
void operationImp() { ... }
}
}
module extension extends original {
class Abstraction {
define void operation2() { imp.operationImp2(); }
}
class Implementor {
define abstract void operationImp2();
}
class ConcreteImplementorA {
void operationImp2() { ... }
}
class ConcreteImplementorB {
void operationImp2() { ... }
}
}
Implementation selection of Abstraction.
+ Downcasts are no longer needed. - This solution is applicable only if just one implementation of Abstraction is used in a program.

module original {
define class Abstraction {
define void operation() {
... implementationOperation1(); ...
}
define abstract void implementationOperation1();
define abstract void implementationOperation2();
}
define class RefinedAbstractionA extends Abstraction {...}
define class RefinedAbstractionB extends Abstraction {...}
}
module implementation1 extends original {
class Abstraction {
void implementationOperation1() {...}
void implementationOperation2() {...}
}
}
module implementation2 extends original {
class Abstraction {
void implementationOperation1() {...}
void implementationOperation2() {...}
}
}