winter semester 17/1 software engineering design...
TRANSCRIPT
![Page 1: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/1.jpg)
Software Engineering Design & Construction
Dr. Michael Eichberg Fachgebiet Softwaretechnik
Technische Universität Darmstadt
Adapter Pattern
Winter Semester 17/18
![Page 2: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/2.jpg)
Foreign Framework
Adapter
FrameworkClass
MyClass
The Adapter Design PatternFit foreign components into an existing design.
2
Intent
![Page 3: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/3.jpg)
GraphicalFramework
+getHeadline() : String+getText() : String
«interface»Node
The Adapter Design Pattern - Illustrated
3
exter
nal
![Page 4: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/4.jpg)
+getDepartment():String
Employee
+getName() : String
Person
+ getAddress():String
Customer
Desired Usage of the Framework
4
intern
al
![Page 5: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/5.jpg)
+getDepartment():String
Employee
+getName() : String
Person
+ getAddress():String
Customer
GraphicalFramework
+getHeadline() : String+getText() : String
«interface»Node
Adapting the Framework
5
external
internal
![Page 6: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/6.jpg)
Client
request()a : Adaptee
Adapter
request()
Target
specificRequest()
Adaptee
«method»{
a.specificRequest();}
a
Object Adapter
6
![Page 7: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/7.jpg)
+getHeadline() : String+getText() : String
EmployeeNodeAdapter
GraphicalFramework
+getHeadline() : String+getText() : String
«interface»Node
adaptee
+getDepartment():String
Employee
+getName() : String
Person
+ getAddress():String
Customer
+getHeadline() : String+getText() : String
CustomerNodeAdapter
adaptee
«method»{
adaptee.getName();}
«method»{
adaptee.getAddress();}
«method»{
adaptee.getName();}
«method»{
adaptee.getDeparment();}
Using Object Adapter
7
![Page 8: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/8.jpg)
Client
request()
Adapter
request()
Target
specificRequest()
Adaptee
«method»{
specificRequest();}
Class Adapter
8
![Page 9: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/9.jpg)
+getHeadline() : String+getText() : String
EmployeeNodeAdapter
GraphicalFramework
+getHeadline() : String+getText() : String
«interface»Node
+getDepartment():String
Employee
+getName() : String
Person
+ getAddress():String
Customer
+getHeadline() : String+getText() : String
CustomerNodeAdapter
«method»{
getName();}
«method»{
getAddress();}
«method»{
getName();}
«method»{
getDeparment();}
Using Class Adapter
9
![Page 10: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/10.jpg)
Takeaway
• Adapter is an effective means to adapt existing behavior to the expected interfaces of a reusable component or framework.
• Two variants: Object and Class Adapter
• Both have their trade-offs.
• Both have problems with the reusability of the adapter.
10
![Page 11: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/11.jpg)
Pimp-my-Library Idiom/Pattern (Scala)
11
Transparently add functionality to “fixed” library classes.
![Page 12: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/12.jpg)
Pimp-my-Library Idiom/Pattern (Scala)
• Define a conversion function to convert your object into the required object and make this conversion implicit to let the compiler automatically perform the conversion when needed. (Transparent generation of object adapters.)
12
Solution Idea
![Page 13: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/13.jpg)
Adding fold to java.lang.String
• Definition of the “Adapter”: Context { implicit class RichString(val string: String) extends AnyVal { def foldIt[T](start:T)(f:(T,Char) => T) : T = { var r = start for(i <- 0 until string.length) r = f(r,string.charAt(i)) r } } }
• As soon as the class RichString is in scope, we can now write: "abc".foldIt("Result:")(_ + _.toShort)
13
A String is basically an ordered sequence of chars. Hence, we expect all standard collection operations.
![Page 14: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/14.jpg)
Advanced Scenario• We want to be able to repeat a certain operation multiple
times and want to store the result in some given mutable store/collection.
14
In Scala's (2.10) mutable collections do not define a common method to add an element to them.
![Page 15: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/15.jpg)
Implementing a repeatAndStore method (initial idea)
object ControlFlowStatements { def repeatAndStore[T, C[T]](
times: Int )(
f: ⇒ T )(
collection: MutableCollection[T, C] ): C[T] = {
var i = 0; while (i < times) { collection += f; i += 1 } collection.underlying
}
}
15
![Page 16: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/16.jpg)
Implementing a repeatAndStore method (naïve approach)
object ControlFlowStatements { import scala.collection.mutable.Set abstract class MutableCollection[T, C[T]](val underlying: C[T]) { def +=(elem: T): Unit } implicit def setToMutableCollection[T](set: Set[T]) = new MutableCollection(set) {
def +=(elem: T) = set += (elem) }
def repeatAndStore[T, C[T]](times: Int)(
f: ⇒ T)(collection: MutableCollection[T, C]): C[T] = { var i = 0; while (i < times) { collection += f; i += 1 } collection.underlying }}
16
![Page 17: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/17.jpg)
object ControlFlowStatements { import scala.collection.mutable.Set abstract class MutableCollection[T, C[T]](val underlying: C[T]) { def +=(elem: T): Unit } implicit def setToMutableCollection[T](set: Set[T]) = new MutableCollection(set) {
def +=(elem: T) = set += (elem) }
def repeatAndStore[T, C[T]](times: Int)(
f: ⇒ T)(collection: MutableCollection[T, C]): C[T] = { var i = 0; while (i < times) { collection += f; i += 1 } collection.underlying }}
Implementing a repeatAndStore method (naïve approach)
17
object CFSDemo extends App { import ControlFlowStatements._
val nanos = repeatAndStore(5) { System.nanoTime() }(new scala.collection.mutable.HashSet[Long]())}
What is the type of nanos?
![Page 18: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/18.jpg)
Implementing a repeatAndStore method.import scala.collection.mutable.{Set,HashSet,Buffer,ArrayBuffer}object ControlFlowStatements{
trait Mutable[-C[_]] { def add[T](collection: C[T], elem: T): Unit }
implicit object SetLike extends Mutable[Set] { def add[T](collection: Set[T], elem: T) { collection += elem } }
implicit object BufferLike extends Mutable[Buffer] { def add[T](collection: Buffer[T], elem: T) { collection += elem } }
def repeat[T, C[T] <: AnyRef: Mutable]( times: Int)(f: ⇒ T)(collection: C[T]): collection.type = { var i = 0 while (i < times) { implicitly[Mutable[C]].add(collection, f); i += 1 } collection }}
18
![Page 19: Winter Semester 17/1 Software Engineering Design ...stg-tud.github.io/sedc/Lecture/ws17-18/5.6-AdapterPattern.pdf · Pimp-my-Library Idiom/Pattern (Scala) • Define a conversion](https://reader036.vdocuments.site/reader036/viewer/2022071000/5fbcaa8239d4d414c2307051/html5/thumbnails/19.jpg)
Implementing a repeatAndStore method.import scala.collection.mutable.{Set,HashSet,Buffer,ArrayBuffer}object ControlFlowStatements{
trait Mutable[-C[_]] { def add[T](collection: C[T], elem: T): Unit }
implicit object Set extends Mutable[Set] { def add[T](collection: Set[T], elem: T) { collection += elem } }
implicit object Buffer extends Mutable[Buffer] { def add[T](collection: Buffer[T], elem: T) { collection += elem } }
def repeat[T, C[T] <: AnyRef: Mutable]( times: Int)(f: ⇒ T)(collection: C[T]): collection.type = { var i = 0 while (i < times) { implicitly[Mutable[C]].add(collection, f); i += 1 } collection }}
19
import ControlFlowStatements._
val nanos_1: Set[Long] = repeat(5){ System.nanoTime() }(new HashSet[Long]())
val nanos_2: Buffer[Long] = repeat(5){ System.nanoTime() }(new ArrayBuffer[Long]())
val nanos_3: nanos_1.type = repeat(5) {System.nanoTime() }(nanos_1)