Mixin based Adaptation of Design Patterns
Virginia Niculescu
a
Faculty of Mathematics and Computer Science, Babes¸-Bolyai University, 1 M. Kog
˘
alniceanu, Cluj-Napoca, Romania
Keywords:
Patterns, Mixins, Composition, Inheritance, Static Binding, Performance, Templates, C++.
Abstract:
Design patterns represent important mechanisms in software development, since a design pattern describes
the core of the solution for a recurrent problem. This core solution emphasizes the participants with their
responsibilities, and their possible relationships and collaborations. In the classical form these solutions are
based on inheritance and composition relationships with a favor on composition. Mixins represents another
important reuse mechanism that increases the level of flexibility of the resulted structure. In this paper, we
investigate the possibility of using mixin for design pattern implementation, providing interesting adaptations.
This approach represents a complementary realization of the design patterns, that brings the advantages of
increased flexibility and statically defined relations between pattern participants.
1 INTRODUCTION
Design patterns are important mechanisms that capture
design expertise and in the same time facilitate struc-
turing of software systems. A design pattern defines
a core solution for a problem which occurs over and
over again in software development. Design patterns
are valuable for emphasizing these recurrent problems,
and of course, for providing the appropriate core so-
lutions. In the classical form these core solutions are
based on inheritance and composition relationships
with a favor on composition.
In (Gamma et al., 1994) design pattern book, it
is stated that the (object) composition is a good alter-
native to inheritance, and so there, an argumentation
is given to favor composition when both relations are
possible. But composition is not always the perfect
solution from all points of view. Method calls are for-
warded to some objects and the responsibility of man-
aging these objects could become a problem (creation,
deletion, updating, isolating). Also, if composition is
used, isolated testing is difficult or even impossible in
some cases.
Since design patterns could be considered building
blocks in code development, it is of interest to ana-
lyze their possible alternative implementations while
preserving their purposes.
Mixins represents another important reuse mech-
anism that increases the level of flexibility of the re-
sulted structure. We intend to prove that mixins rep-
a
https://orcid.org/0000-0002-9981-0139
resent a good alternative to be used when defining
design patterns. Our approach for realizing patterns
promotes the benefits of static knowledge within pat-
terns by moving such information to mixin units. This
approach represents a complementary realization of
the design patterns, that brings the advantage of stati-
cally defined relations between pattern participants.
Mixin implementation is different from one lan-
guage to another. Most of the implementations are
based on multiple inheritance, but there are also other
specific implementations. We have chosen to use C++
for exemplification, but the design solutions remain
the same for other languages.
The reason for this investigation is given also by
the fact that static definitions are considered in general
more efficient since the number of operations to be
executed at the runtime is reduced.
If the component instantiation and interconnection is
done statically, when the system is built, then we may
expect a better performance from the time execution
point of view.
The paper is structured as follows: Next section
introduces mixins, and their C++ realization mecha-
nisms, and the next presents a comparative analysis of
static versus dynamic code composition. In Section
4 we describe possible mixin based adaptations for
several design patterns, with the advantages and the
implied challenges. Conclusions and planned future
work are presented in Section 5.
Niculescu, V.
Mixin based Adaptation of Design Patterns.
DOI: 10.5220/0010444702610268
In Proceedings of the 16th International Conference on Evaluation of Novel Approaches to Software Engineering (ENASE 2021), pages 261-268
ISBN: 978-989-758-508-1
Copyright
c
2021 by SCITEPRESS Science and Technology Publications, Lda. All rights reserved
261
2 MIXINS
In object-oriented programming languages, a mixin
is a class that contains methods to be used by other
classes without having to be the parent class of those
other classes. How those other classes gain access to
the mixin’s methods depends on the language (Bracha
and Cook, 1990; Flatt et al., 1998).
Mixins can use the inheritance relation to extend
the functionality of various base classes with the same
set of features, but without inducing an “is-a” semantic
relation. This is why, when mixins are used, the term
is rather “included” rather than “inherited”. Using a
mixin is not a form of specialization but is rather a
mean to collect functionality, even if the implementa-
tion mechanism is based on inheritance. A subclass
could inherit most or all of its functionality by in-
heriting from one or more mixins through multiple
inheritance.
A mixin can also be viewed as an interface with im-
plemented methods. It is what has been introduced in
Java and C# through default interface methods. There
are also opinions that consider that the default inter-
face methods represent traits implementation (Bono
et al., 2014).
In C++ mixins could be defined using templates
(Smaragdakis and Batory, 2000), by using so called
policies.
2.1 C++ Policies
C++ policies could be considered a very interesting
and useful metaprogramming mechanism that allows
behavior infusion in a class through templates and
inheritance (Alexandrescu, 2001; Abrahams and Gur-
tovoy, 2003). C++ template policies represent an in-
teresting tool that could also be used to create classes
based on ad-hoc hierarchies, even if the policies’ initial
intent was different. In the same time, they represent a
solid mechanism to implement mixins.
A policy defines a class template interface; it is a
class or class template that defines an interface as a
service to other classes (Alexandrescu, 2001).
A key feature of the policy idiom is that, usually,
the template class will derive from (make itself a child
class of) each of its policy classes (template parame-
ters).
More specifically, policy based design implies the
creation of a template class, taking several type pa-
rameters as input, which are instantiated with types
selected by the user – the policy classes, each imple-
menting a particular implicit interface – called policy,
and encapsulating some orthogonal (or mostly orthog-
onal) aspect of the behavior of the template class.
Policies have direct connections with C++ template
metaprogramming and C++ traits which have been
used in many language libraries; classical examples
are:
string
class, I/O streams, the standard contain-
ers, and iterators. As emphasized in (Alexandrescu,
2001), in comparison with C++ traits they are more
oriented on behavior instead of types. They are also
considered a template implementation of the Strategy
design pattern.
2.2 CRTP Pattern
The CRTP (Curiously Recurring Template Pattern)
is in a way similar to policy mechanism being en-
countered when we derive a class from a template
class given the class itself as a template parameter
for the base class (Abrahams and Gurtovoy, 2003;
Nesteruk, 2018). It is a parameterization of the base
class with the derived class. In a concrete usage
of these classes, the invocation of method
aMethod
through a
Base<Child>
object will lead to the execu-
tion of the variant defined in the
Child
class (Listing
1).
1 t e m p l a t e <typen a m e T>
2 c l a s s Base {
3 p u b l i c :
4 v o i d aMet hod ( ) {
5 T& c h i l d = s t a t i c c a s t <T&>(
*
t h i s ) ;
6 \\ u s e th e ' c h i l d ' o b j e c t . . .
7 }
8 }
9 c l a s s C h i l d : p u b l i c Ba sed<C h i ld> {
10 p u b l i c :
11 v o i d aMet hod ( ) {
12 \\ s p e c i f i c d e f i n i t i o n o f t h e m ethod
13 \\ i n t h e C h i l d c l a s s
14 }
15 } ;
Listing 1: An example of using CRTP.
So, CRTP can be used in order to avoid the neces-
sity for virtual methods, which come with a runtime
overhead. In addition, CRTP can be used for adding
functionality, as the mixins, too.
3 ARGUMENTATION: STATIC
VERSUS DYNAMIC
The inheritance based development comes with several
well-known problems, as the following two:
The Fragile Base Class Problem changes to a
base class can potentially affect a large number
of descendant classes and also the code that uses
them.
The Inflexible Hierarchy Problem – a class taxon-
omy created based on inheritance is not easy to
ENASE 2021 - 16th International Conference on Evaluation of Novel Approaches to Software Engineering
262
maintain, the new use-cases could impose adapta-
tion and transformation that are not easy to obtain.
A hybrid taxonomy that is based also on mixins is
much more flexible and adaptable; changes could be
better isolated.
Polymorphism is one of the most important object-
oriented programming advantage. Virtual methods
represent a mechanism through which the dynamic
subtype polymorphism can be achieved. Still, they
come with a performance cost since for their imple-
mentation a virtual methods table should be used for
each class that defines virtual methods. Beside the
memory overhead there is also an important execution
time overhead, due to the indirection needed in calling
virtual methods.
In their classical form, almost all of the fundamen-
tal patterns are based on subtype polymorphism. This
is a good feature that assures flexibility, but it is not
so efficient from the running time point of view. If we
can provide more information that could be evaluated
at the compile time we may increase the performance.
The proposed approach for patterns’ definition pro-
motes the benefits of static knowledge by moving in-
formation to components that could be evaluated at the
compile time.
It can be argued that, in this way, we may lose
the advantage of the possible dynamic reconfiguration;
this is not exactly true since we may still dynamically
choose between several configurations that are stati-
cally defined.
Separation between the static parts of the software
design from the dynamic parts of the system behav-
ior were proposed before, also specifically to patterns
(Eide et al., 2002; Alexandrescu, 2001; Nesteruk,
2018). This separation makes the software design
more amenable to analysis and effective optimization.
In (Eide et al., 2002) the adaptation is done by identi-
fying the parts of the pattern that correspond to static
(compile-time or link-time) knowledge about the pat-
tern and its participants, but this process was specific
to individual uses of a pattern: each time a pattern is
applied, the situation dictates whether certain parts of
the pattern correspond to static or dynamic knowledge.
Typically, mixins are defined based on classes and
they represent static mechanisms of functionality com-
position. Still, there are also some variations called
dynamic mixins which are applied to objects at run-
time, extending the object with new fields and methods.
Dynamic mixins represent modular means of develop-
ing features or roles that can be composed with objects
at run-time. Usually, dynamically typed languages
are well suited to support dynamic mixins. In (Bur-
ton and Sekerinski, 2014) patterns adaptation using
dynamic mixins is discussed, but just in the context of
a teoretically defined language.
Instead of trying to extend the objects, we intend
to provide general patterns realizations that increase
the static part of them by using clasical, static mixins.
In order to demonstrate the proposed adaption, we
use C++ language with the corresponding mixin mech-
anism based on templates. The pattern adaptation
is not necessarily connected to C++ language, but it
could be applied for any other language that accept
mixins.
4 PATTERNS’ ADAPTATION
As a general rule, the adaptation tries to transform an
object composition relation that exists in the classi-
cal pattern definition into a mixin static composition.
For an increased flexibility, a specialization relation
could be also replaced to a mixin composition i.e.
when an abstraction could be specialized through a
mixin inclusion. This is going to be seen in the adap-
tation of the Template Method pattern in Section 4.1.
The replacement involves a transformation of at least
one class from the pattern structure into a mixin class.
Usually, only one relation can be replaced by a mixin
composition.
In order to identify the possible candidates, we may
follow a general strategy that contains the following
steps:
identify all the composition relations;
exclude ”one-to-many” compositions;
identify specialization relations for which seman-
tically there is not (or can be excluded) an “is-a”
relation.
We will present in what is follows adaptations for sev-
eral patterns from all the three categories: structural,
behavioral, and creational. For each pattern we will
present the transformation that includes mixins, based
on the structural diagram taken from Design Pattern
book (Gamma et al., 1994): we emphasize what is
excluded (using red color) and what is added (using
blue color). In addition, for clarifying the solutions,
we will present code snippets of the corresponding
concrete C++ implementation.
4.1 Template Method
For the Template Method pattern, we use an inversion
of specialization direction: instead of specialize an
abstraction by deriving a new class from it, we allow
it to be specialized through a mixin (Figure 1). The
specialization inheritance relation is replaced with a
mixin inheritance.
Mixin based Adaptation of Design Patterns
263
1 t e m p l a t e <ty pename T>
2 c l a s s TMClass : p u b l i c T{
3 p u b l i c :
4 vo i d t e m p l a t e m e t h o d ( ) {
5 T : : p r i m i t i v e O p e r a t i o n 1 ( ) ;
6 T : : p r i m i t i v e O p e r a t i o n 2 ( ) ;
7 }
8 } ;
9 c l a s s C o n c r e t e C l a s s {
10 p u b l i c :
11 vo i d p r i m i t i v e O p e r a t i o n 1 ( ) { . . . }
12 vo i d p r i m i t i v e O p e r a t i o n 2 ( ) { . . . }
13 } ;
14 / / / / / / / / / us a g e / / / / / / / / /
15 TMClass<C o n c r e t e C l a s s> a ;
16 a . t e m p l a t e m e t h o d ( ) ;
Listing 2: Adaptation of Template Method pattern.
More concretely, the class
TMClass
that defines
the
template method
is not longer abstract and it is
allowed to receive a mixin for specialization. The
code in Listing 2 emphasizes this.
Figure 1: The adaptation of Template Method pattern.
Compared to the classical Template Method pat-
tern, the specialization is obtained from a mixin that
implements the primitive operations, instead of defin-
ing subclassing for specialization; this preserves the
focus on the class that defines the algorithm, and lets
the classes that implement primitive operation to be
independent. This independence could come with a
cost related to the state sharing – they will not inherit
the state of the
TMClass
if this exists. But, this could
be solved by giving this state as a parameter for the
primitive methods. In addition, the type of this state
could be parameterized and make the pattern more
generic.
The independence of the concrete classes from the
class that defines the template method, allows a mixin
class to be used by more other classes (that defines
template methods), the constraint being defined only
by the condition of defining all primitive operations.
Concluding, we may say that instead of having
many specializations of a class, we have a parame-
terized class, that it is specialized through the con-
crete(mixin) class parameters. The coupling between
classes is much lower, leading to only one relation for
a concrete execution.
Remark:
For Factory Method pattern a similar ap-
proach could be followed – instead of letting the sub-
classes to specialize the factory methods, mixins could
be given.
4.2 Memento
Memento is a very simple pattern that intend to provide
a way to capture the internal state of an object at some
moment of time and offer the possibility to restore that
state in the future.
The classical implementation is based again on
composition – the state is store into an object which
is an instance of a class created only for this purpose.
This composition is replaced with a mixin composi-
tion.
Figure 2: The adaptation of Memento pattern.
The class
Memento
could be defined as a mixin, and
the
Originator
could use it (include it) in order to
store and restore a specific state. The
Caretaker
is
not longer necessary since the memento object is not
stored outside the originator object. The client just has
to invoke the originator object to preserve or restore
its state.
In addition, the classes could be parameterized
with the type of the state for a more general definition
of
Memento
mixin. In this way the mixin could be used
for differnt originator classes.
The encapsulation is still preserved since inside
Memento
the state is stored and managed in the
protected section.
1 t e m p l a t e < c l a s s S>
2 c l a s s Memento {
3 p r o t e c t e d :
4 S s t a t e ;
5 vo i d s e t S t a t e ( S s ) { s t a t e = s ; }
6 S g e t S t a t e ( ) { r e t u r n s t a t e ; }
7 } ;
8 t e m p l a t e < c l a s s S , t e m p l a t e <c l a s s > c l a s s T>
9 c l a s s O r i g i n a t o r : p u b l i c T<S>{
10 S s t a t e ;
11 p u b l i c :
12 O r i g i n a t o r ( S s t a t e ) { t h i s >s t a t e = s t a t e ; }
13 vo i d c re a te M e me n to ( ) {
14 T<S > :: s e t S t a t e ( t h i s > s t a t e ) ; }
15 vo i d s e tMemento ( ) { s t a t e = T<S>:: g e t S t a t e ( ) ; }
16 vo i d u p d a t e ( ) {
17 / / t h e s t a t e i s u p d a t e d
18 }
19 } ;
20 / / / / / / / / / us a g e / / / / / / / / /
21 O r i g i n a t o r <S t a t e , Memento> o b j e c t ( ) ;
22 o b j e c t . c r e at e Me m e n t o ( ) ;
23 o b j e c t . u p d a t e ( ) ;
24 o b j e c t . set M e m e n t o ( ) ;
Listing 3: Adaptation of Memento pattern.
ENASE 2021 - 16th International Conference on Evaluation of Novel Approaches to Software Engineering
264
Figure 2 emphasizes the transformation of the pat-
tern structure, and the Listing 3 gives details about the
implementation. The
Originator
class is parameter-
ized with the type of the state (
S
) and with a
Memento
that depends on that state type. The
Memento
is in-
cluded as a mixin.
4.3 Bridge
Bridge pattern connects an abstraction with possible
concrete implementations of its parts. The adaptation
changes the composition relation between the abstrac-
tion object and the corresponding implementation ob-
ject into a class relation the abstraction “is made
concrete” by infusion into it a concrete implementa-
tion through a mixin.
Figure 3: The adaptation of Bridge pattern.
Figure 3 emphasizes the transformation: the ab-
stract superclass
Implementator
is no longer necessary
since a concrete implementor class could be directly
given to the
Abstraction
class, and there is no need
for virtual methods.
As was specified, mixin inheritance doesn’t have to
be seen as implementing an “is a” relationship. Other-
wise the proposed adaptation would lead to the conclu-
sion that ’an abstraction is a kind of implementation’
which of course would be wrong. But as the mixin
definition says - the relation between the class and a
mixin means that a functionality is included. In Bridge
pattern, the
Implementor
provides a concrete imple-
mentation for the abstract part of the class.
1 t e m p l a t e <ty pename T>
2 c l a s s A b s t r a c t i o n : p u b l i c T{
3 p u b l i c :
4 vo i d o p e r a t i o n ( i n t para m s ) {
5 T : : o p e r a t i o n i m p ( pa rams ) ; }
6 } ;
7 c l a s s Co n cr e t e I m p l e m e n t o r A {
8 p u b l i c :
9 vo i d o p e r a t i o n i m p ( i n t p a r a m s ) { p a r a ms ++; }
10 } ;
11 / / / / / / / / / us a g e / / / / / / / / /
12 A b s t r a c t i o n <C o nc r et e I m p l e m e nt o rA> e n t i t y ;
13 e n t i t y . o p e r a t i o n ( 0 ) ;
Listing 4: Adaptation of the Bridge pattern.
For Bridge pattern we may also provide a real-
ization based on CRTP C++ pattern that changes the
relation between “abstraction” and “implementor”
this alternative variant is presented in Listing 5. This
variant has similar characteristics.
1 t e m p l a t e <ty pename T>
2 c l a s s CR T P A b s t r a c t io n {
3 p u b l i c :
4 vo i d o p e r a t i o n ( i n t para m s ) {
5 s t a t i c c a s t <T
*
>( t h i s )>o p e r a t i o n i m p ( pa rams ) ;
6 }
7 } ;
8 c l a s s CRTP I mplemen tor A :
9 p u b l i c C R T P A b st r ac t io n<CRTP Im plemento rA>{
10 p u b l i c :
11 vo i d o p e r a t i o n i m p ( i n t p a r a m s ) { p a r a ms ++;}
12 } ;
13 / / / / / / / / / us a g e / / / / / / / / /
14 CR T P Ab s t r a c t i o n<CRTP Implementor A> e n t i t y ;
15 e n t i t y . o p e r a t i o n ( 0 )
Listing 5: Adaptation of the Bridge pattern – CRTP variant.
It can be argued that using this solution the client
doesn’t have the possibility to move dynamically from
one implementor to another. This is not true, because if
the all possible variants are known, the change means
only to choose between several predefined variants –
factory methods could be used. The drawback comes
more from the extensibility point of view, when other
new concrete implementors are intended to be added to
the system – but since the new implementors should be
statically defined, this leads to a problem with classical
implementation, too.
4.4 Mediator
The Mediator pattern is used when we need to have an
object that encapsulates the interaction between a set
of other objects. The pattern promotes low coupling
by avoiding objects to refer each other explicitly.
For the Mediator pattern the adaptation is a lit-
tle bit more complex as it can be seen in the Figure
4. The adaptation imposes also a class factorization:
Mediator
class should be split and so
StateMediator
class is created in order to store the existing objects.
The mediator classes, as ConcreteMediator, will de-
fine only the interaction between objects (colleagues)
and not their creation and storage. A ConcreteMedi-
ator class will be used as a mixin to be included into
StateMediator class.
Figure 4: The adaptation of Mediator pattern.
Mixin based Adaptation of Design Patterns
265
1 t e m p l a t e <t e m p l a t e <c l a s s S > c l a s s T>
2 c l a s s C o l l e a g u e {
3 p r o t e c t e d :
4 S t a t e M e d i a t o r<T>
*
s t a t e ;
5 p u b l i c :
6 C o l l e a g u e ( S t a t e M e d i a t o r<T>
*
s t a t e ) {
7 t h i s >s t a t e = s t a t e ; }
8 S t a t e M e d i a t o r<T>
*
g e t S t a t e ( ) { r e t u r n s t a t e ; }
9 vo i d c han g e d ( ) {
10 s t a t e >r e a c t i o n t o c h a n g e ( t h i s ) ; }
11 } ;
12 t e m p l a t e <t e m p l a t e <c l a s s S > c l a s s T>
13 c l a s s C o n c r e t e C o l l e a g u e 1 : p u b l i c C o l l e a g u e<T>{
14 p u b l i c :
15 C o n c r e t e C o l l e a g u e 1 ( S t a t e M e d i a t o r<T>
*
s t a t e )
16 : C o l l e a g u e<T>( s t a t e ) {}
17 vo i d u p d a t e ( ) {
18 / / u p d a t e s o m e t h i n g f o r ' t h i s ' c o l l e a g u e
19 C o l l ea g u e<T> :: ch a ng e d ( ) ; }
20 } ;
21 t e m p l a t e <t e m p l a t e <c l a s s S > c l a s s T>
22 c l a s s S t a t e M e d i a t o r : p u b l i c T<S t a t e M e d i a t o r <T>>
23 { p r o t e c t e d :
24 C o n c r e t e C o l l e a g u e 1
*
c1 ;
25 C o n c r e t e C o l l e a g u e 2
*
c2 ;
26 p u b l i c :
27 v o i d s e t C o n c r e t e C o l l e a g u e 1 (
28 C o n c r e t e C o l l e a g u e 1<T>
*
c ) { v1=c ; }
29 v o i d s e t C o n c r e t e C o l l e a g u e 2 (
30 C o n c r e t e C o l l e a g u e 2<T>
*
c ) { v2=c ; }
31 C o n c r e t e C o l l e a g u e 1<T>
*
g e t C o n c r e t e C o l l e a g u e 1 ( ) {
r e t u r n c1 ; }
32 C o n c r e t e C o l l e a g u e 2<T>
*
g e t C o n c r e t e C o l l e a g u e 2 ( ) {
r e t u r n c2 ; }
33 } ;
Listing 6: Adaptation of the Mediator pattern – Colleague,
ConcreteColleague1, and StateMediator classes.
An object composition is preserved for storing the
set of objects that need to interact; so, the object com-
position is used for an object of type
StateMediator
,
which is used in order to store the team of participants.
The behavior is split out of this class and it is included
through a mixin class – ConcreteMediator.
1 t e m p l a t e <ty pename T>
2 c l a s s Co n c r e t e M e d i a t o r A {
3 p u b l i c :
4 vo i d r e a c t i o n t o c h a n g e ( C o l l e ag u e<Co n c re t eM e di a to r A
>
*
s ) {
5 S t a t e M e d i a t o r <Co n c r e t e M e d i a to r A >
*
s t a t e =
6 s>g e t S t a t e ( ) ;
7 C o n c r e t e C o l l e a g u e 1<C on c r e t e M e d i a t o r A >
*
c1 =
8 s t a t e >g e t C o n c r e t e C o l l e a g u e 1 ( ) ;
9 C o n c r e t e C o l l e a g u e 2<C on c r e t e M e d i a t o r A >
*
c2 =
10 s t a t e >g e t C o n c r e t e C o l l e a g u e 2 ( ) ;
11 / / u p d a t e b a s e d on s p e c i f i c m e d i a t o r s t r a t e g y
12 }
13 } ;
14 / / / / / / / / / us a g e / / / / / / / / /
15 S t a t e M e d i a t o r <Co n c r e t eM e di a to r A> d s ;
16 / / c r e a t e t h e t eam
17 ds . s e t C o n c r e t e C o l l e a g u e 1 ( new Co n c r e t e C o l l e a g u e 1<
C o n c r e t e M e d ia t or A >(&ds ) ;
18 ds . s e t C o n c r e t e C o l l e a g u e 2 ( new Co n c r e t e C o l l e a g u e 2<
C o n c r e t e M e d ia t or A >(&ds ) ;
19 / / u p d a t i n g one d e t e r m i n e a c h a n ge f o r t h e o t h e r s
20 ds . g e t C o n c r e t e C o l l e a g u e 1 ( )>u p d a t e ( ) ;
Listing 7: Adaptation of the Mediator pattern
ConcreteMediator class and usage.
If we consider the example given in (Gamma et al.,
1994) with graphic widgets (fields, boxes, ...) this will
translate into a state mediator that store the graphical
objects and several behavior mediators that establish
the particular reaction after a specific widget selection.
Mediator is another example (beside of Decorator)
that combines mixin composition with object compo-
sition: for the state of the team, object composition is
used, but the specific behavior mediator is specified/in-
fused as a mixin.
4.5 Builder
Creational design patterns could be adapted, too.
Builder has a nice solution, in which object composi-
tion between the director and the builder is changed
into a mixin composition.
Figure 5: The adaptation of Builder pattern.
From the Figure 5 it can be seen that the class
Director
is infused with
Builder
specific behavior,
being able to construct, but also to get the result that is
specific to a particular builder – e.g.
ConcreteBuilder
.
Implementation details are give in Listing 8.
1 t e m p l a t e <ty pename T ,
2 typen a m e S = t ypename T : : p a r t t y p e >
3 c l a s s P r o d u c t {
4 S p a r t 1 , p a r t 2 ;
5 p u b l i c :
6 P r o d u c t ( S p1 , S p2 ) {
7 t h i s >p a r t 1 = p1 ;
8 t h i s >p a r t 2 = p2 ; }
9 } ;
10 c l a s s C o n c r e t e B u i l d e r {
11 p u b l i c :
12 t y p e d e f i n t p a r t t y p e ;
13 v o i d B u i l d P a r t 1 ( ) { p a r t 1 = 1 0 ; }
14 v o i d B u i l d P a r t 2 ( ) { p a r t 2 = 2 0 ; }
15 Pr o d u c t<C o n c r e t e B u i l d e r > g e t R e s u l t ( ) {
16 r e t u r n P r o d u c t<C o n c r e t e B u i l d e r >(p a r t 1 , p a r t 2 ) ;
17 }
18 p r i v a t e :
19 p a r t t y p e p a r t 1 , p a r t 2 ;
20 } ;
21 t e m p l a t e <ty pename T>
22 c l a s s D i r e c t o r : p u b l i c T{
23 p u b l i c :
24 v o i d c o n s t r u c t ( ) {
25 T : : B u i l d P a r t 1 ( ) ;
26 T : : B u i l d P a r t 2 ( ) ; }
27 Pr o d u c t<T> g e t R e s u l t ( ) { r e t u r n T : : g e t R e s u l t ( ) ; }
28 } ;
29 / / / / / / / / / us a g e / / / / / / / / /
30 D i r e c t o r<Co n c r e t e B u i l d e r > a ;
31 a . c o n s t r u c t ( ) ;
32 P r o d u c t<C o n c r e t e B u i l d e r > pa = a . g e t R e s u l t ( ) ;
Listing 8: Adaptation of Builder pattern.
The link between the builder and its specific prod-
uct is done through the parameter of
Product
class; the
result will have the type
Product<ConcreteBuilder>
.
In this case, the builder specializes also the product.
Though this transformation, the classical object com-
ENASE 2021 - 16th International Conference on Evaluation of Novel Approaches to Software Engineering
266
position between
aDirector
and
aBuilder
is trans-
formed into a mixin composition.
4.6 Fac¸ade
Facade pattern provides a unified interface to a set of
interfaces in a subsystem; this higher-level interface
makes the subsystem easier to use.
Clients communicate with the subsystems through
Fa
c¸
ade that has the responsibility to forward the re-
quests from the clients to the appropriate subsystem. If
the number of interfaces in that set of interfaces (sub-
systems) remains fix, then
Facade
could be defined as
a combination of mixins that correspond to the aggre-
gated interfaces. Fa
c¸
ade controller is one of the most
encountered use-cases.
Here, the definition of mixin composition is di-
rectly applied: the Fa
c¸
ade is created as a composition
of several units (classes). Listing 9 presents a sim-
ple variant, with three subsystems and two possible
requests from the client.
1 t e m p l a t e <ty pename SUBSYSTEM A ,
2 ty pename SUBSYSTEM B , t y p e n a m e SUBSYSTEM C>
3 c l a s s F aca d e :
4 p u b l i c SUBSYSTEM A , SUBSYSTEM B , SUBSYSTEM C{
5 p u b l i c :
6 v o i d r e q u e s t 1 ( ) {
7 SUBSYSTEM A : : f u n c t i o n A ( ) ;
8 SUBSYSTEM B : : f u n c t i o n B ( ) ;
9 }
10 v o i d r e q u e s t 2 ( ) {
11 SUBSYSTEM C : : f u n c t i o n C ( ) ;
12 }
13 } ;
14 c l a s s Sub S yste mA {
15 p u b l i c :
16 v o i d f u n c t i o n A ( ) {
17 c o u t << ” sub s y s t e m A f u n c t i o n A” << e n d l ;
18 }
19 } ;
20 / / s i m i l a r c o d e f o r Sub Syst e m B an d Sub S y s temC
21 / / / / / / / / / us a g e / / / / / / / / /
22 F a c a d e<Sub S yst emA , Sub Syst emB , S ub Sy stem C> s ;
23 s . r e q u e s t 1 ( ) ;
24 s . r e q u e s t 2 ( ) ;
Listing 9: Adaptation of Fac¸ade pattern.
4.7 Discussion and Counterexamples
Even the transformation could be applied for many pat-
terns, still there are some patterns for which this kind
of adaptation is not possible in good conditions. They
are generally characterized by the following possible
aspects:
the life time of the associated entities/objects is
different;
the number of associated entities could be dynami-
cally changed;
a particular state directly determined the behavior
of many objects.
If we consider an adaptation of the Iterator pattern that
makes the associated collection to use an
Iterator
mixin, we restrict the behavior to only one iterator
associated to a collection object that has the same life
time as the collection object. This mixin implemen-
tation would correspond to an older style of imple-
menting collections, that includes a cursor between
collection’s elements. The classical Iterator pattern
increases the flexibility in iterating the elements, by
separating iteration from collection.
State pattern deals with situations when the actual
state controls a ’system’ behavior. Including the state
into the system by using mixins would make difficult
to allow this state, and implicitely the behavior, to
change dynamically.
The Observer pattern introduces a behavior depen-
dency on the state of an external object. Theoretically,
for Observer would be possible to go on using a similar
approach with that used for Mediator, but in this case
the benefits are less than the introduced disadvantages;
the problem is given by the fact that the list of the
observers is dynamically changed, and each observer
could react differently and independently.
Considering only the Composite pattern structure,
we may say that a similar approach to that used for Dec-
orator could be taken. But, by semantic, Composite is
intrinsically related to objects and their compositions.
In addition, for Composite it is very common to have
“one-to-many” composition: an aggregate node could
contain one, two or more other nodes, and this number
is not fixed for the entire structure.
This highly dynamic behavior makes these exam-
ples of patterns unappropriated to be adapted using
static mixins.
Still, as emphasized before, there are many pat-
terns for which the mixin based adaptation is both
easy and advantageous. In addition we may men-
tion: Adapter pattern adaptation is straightforward,
the obtained advantage is that a general parameterized
Adapter class could be defined for a particular Target
interface and specific requests; Strategy is often pre-
sented as a use case of using C++ policies; variants of
Decorator was extendly analyzed in (Niculescu, 2020;
Niculescu et al., 2020); a similar approach to that used
for Decorator can be used for Chain of responsibility
pattern: the handlers could be recursively added as
mixins.
5 CONCLUSIONS
Programming based on static instantiation and inter-
connection (performed when the program is built in-
stead of when the program is executed) is an approach
that offers a good potential for performance. We have
presented an adaptation of the fundamental design
Mixin based Adaptation of Design Patterns
267
patterns based on using mixins. In general, the adap-
tation replaces object composition with mixin compo-
sition. The resulted solutions provide the advantages
borrowed from mixins: flexibility, low coupling, and
static defined compositions.
The adaptations were illustrated using C++ mix-
ins, but this doesn’t mean that other languages with
their mixins kind of composition cannot be used. De-
fault interfaces are mechanisms that are now present
in Java and C# and they are considered to allow mixin
composition.
A comprehensive analysis of the possible adapta-
tion of all fundamental design patterns described in
(Gamma et al., 1994) would be interesting, but maybe
even more interesting is the analysis of the impact
of using these adapted patterns in concrete systems
development. We may expect improved execution
time, and better opportunities for testing and optimiza-
tion. These represent the subjects of the planned future
work.
REFERENCES
Abrahams, D. and Gurtovoy, A. (2003). C++ Template
Metaprogramming: Concepts, Tools, and Techniques
from Boost and Beyond. Addison-Wesley.
Alexandrescu, A. (2001). Modern C++ design: generic
programming and design patterns applied. Addison-
Wesley.
Bono, V., Mensa, E., and Naddeo, M. (2014). Trait-oriented
programming in java 8. In Proceedings of the 3rd
PPPJ, pages 181–186. ACM.
Bracha, G. and Cook, W. (1990). Mixin-based inheritance.
In Proceedings of the OOPSLA/ECOOP 1990, pages
303–311. ACM.
Burton, E. and Sekerinski, E. (2014). Using dynamic mixins
to implement design patterns. In Proceedings of the
19th EuroPLoP, page 1–19. ACM.
Eide, E., Reid, A., Regehr, J., and Lepreau, J. (2002). Static
and dynamic structure in design patterns. In Proceed-
ings of the 24th ICSE, ICSE ’02, page 208–218. ACM.
Flatt, M., Krishnamurthi, S., and Felleisen, M. (1998).
Classes and mixins. Association for Computing Ma-
chinery.
Gamma, E., Helm, R., Johnson, R., and Vlissides, J. (1994).
Design Patterns: Elements of Reusable Object Ori-
ented Software. Addison Wesley.
Nesteruk, D. (2018). Design Patterns in Modern C++.
Reusable Approaches for Object-Oriented Software
Design. Apress.
Niculescu, V. (2020). Efficient decorator pattern variants
through c++ policies. In Proceedings of the 15th
ENASE, pages 281–288. SciTePress.
Niculescu, V., Sterca, A., and Bufnea, D. (2020). Should
decorators preserve the component interface? CoRR,
abs/2009.06414.
Pikus, F. G. (2019). Hands-On Design Patterns with C++:
Solve common C++ problems with modern design pat-
terns and build robust applications. Packt Publishing.
Smaragdakis, Y. and Batory, D. (2000). Mixin-based pro-
gramming in c++. In Proceedings of the 2nd GCSE,
Lecture Notes in Computer Science. Springer.
ENASE 2021 - 16th International Conference on Evaluation of Novel Approaches to Software Engineering
268