← Back to list

ABAP Entwurfsmuster 2: Abstract Factory

Design Pattern : Abstract Factory in ABAP — Creational Design Patterns

urcm · 2024-05-08 09:56 · 0 claps · 6.2 min read
#abap #sap #design-patterns #entwurfsmuster #abstract-factory-pattern
Open on Medium ↗
Wiki topics: TLS · Design Tools & Workflow

ABAP Entwurfsmuster 2: Abstract Factory

Design Pattern : Abstract Factory in ABAP — Creational Design Patterns

Erstellt mit Adobe Firefly by @urcm

Erstellt mit Adobe Firefly by @urcm

Das Abstract Factory ist ein kreatives Entwurfsmuster (eng. Creational Design Patterns ), das verwendet wird, um Familien von miteinander verbundenen Klassen zu erstellen, ohne die spezifischen Klassen zu instanziieren, auf die Sie angewiesen sind. Es bietet eine Schnittstelle, mit der Clients Produkte aus einer Produktfamilie erstellen können, ohne die Implementierungsklassen der Produkte kennen zu müssen.

The Abstract Factory Pattern is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes, in simpler terms the Abstract Factory Pattern is a way of organizing how you create groups of things that are related to each other. ***

Vorteile der Abstract Factory:

Abstraktion von konkreten Klassen: Durch das Abstract Factory Pattern ist es möglich, die Erzeugung von Objekten von deren Verwendung zu trennen. Auf diese Weise wird vermieden, dass der Client-Code von den spezifischen Implementierungen der zu erstellenden Objekte abhängig ist.

Flexibilität und Austauschbarkeit: Durch die Verwendung des Abstract Factory Patterns ist es möglich, verschiedene Familien von Objekten zu erzeugen, indem unterschiedliche Fabrikimplementierungen verwendet werden. Es ermöglicht den einfachen Austausch von Produktfamilien, ohne dass der Client-Code geändert werden muss.

Konsistenz und Kapselung: Durch das Muster wird die Konsistenz gefördert, indem sichergestellt wird, dass Objekte einer spezifischen Familie gemeinsam erstellt und zusammenarbeiten. Darüber hinaus werden die Details der Objekterzeugung in separaten Fabrikklassen gekapselt, was zu einer verbesserten Wartbarkeit und Lesbarkeit des Codes führt.

Einfache Skalierbarkeit: Es ist möglich, neue Fabriken zu erstellen und sie mit den entsprechenden Schnittstellen für die Implementierung neuer Produktfamilien auszustatten. Ohne den bestehenden Code ändern zu müssen, wird die Skalierbarkeit des Systems verbessert.

Testbarkeit: Die Erzeugung von Objekten in Fabrikklassen ist durch das Abstract Factory Pattern erleichtert, was auch das Testen vereinfacht. Das ermöglicht das Einsetzen von Mock-Objekten für Tests oder die Simulation der Objekterzeugung, um verschiedene Szenarien zu testen.

Problem:

In einer Zoo-Applikation mit den Klassen besteht das Problem darin, dass die Erstellung von Tierobjekten stark mit der Verwendung dieser Objekte gekoppelt ist. Ohne die Verwendung des Abstract Factory Patterns müsste der Client-Code, der die Tierobjekte erstellt, explizit die konkreten Klassen wie Cat und Dog kennen und instanziieren. Dies führt zu einem starken Abhängigkeitsproblem, da Änderungen an den Klassen direkt im Client-Code reflektiert werden müssen. Wenn zum Beispiel eine neue Tierart wie "Elefant" hinzugefügt wird, müsste der Client-Code entsprechend aktualisiert werden, um die Instanziierung von Elefantenobjekten zu ermöglichen. Dies führt zu einem unübersichtlichen und schwer zu wartenden Code.

Lösung:

Die Verwendung des Abstract Factory Patterns löst dieses Problem, indem eine abstrakte Fabrik definiert wird, die die Erstellung von Tierobjekten kapselt. Eine konkrete Fabrik wird dann implementiert, um Tierobjekte einer bestimmten Familie zu erzeugen, z. B. CatFactory für Katzen und DogFactory für Hunde. Dadurch wird die Erstellung von Tierobjekten von deren Verwendung entkoppelt. Der Client-Code muss nur die abstrakte Fabrik kennen und verwenden, um Tierobjekte zu erstellen, ohne die konkreten Klassen zu kennen. Wenn eine neue Tierart hinzugefügt wird, muss nur eine neue konkrete Fabrik implementiert werden, ohne den Client-Code zu ändern. Dies verbessert die Flexibilität, Wartbarkeit und Erweiterbarkeit der Zoo-Applikation erheblich.

Im folgenden Beispiel gibt es eine Klassendefinition ohne Verwendung der Abstract Factory-Methode.

Erstellt mit PlantUML

Erstellt mit PlantUML

class lcl_animal definition abstract.
  public section.
    methods: make_sound abstract returning value(rv_sound) type string.
endclass.

class lcl_dog definition inheriting from lcl_animal.
  public section.
    methods: make_sound redefinition.
endclass.

class lcl_cat definition inheriting from lcl_animal.
  public section.
    methods: make_sound redefinition.
endclass.

class lcl_dog implementation.
  method make_sound.
    rv_sound = 'Woof!'.
  endmethod.
endclass.

class lcl_cat implementation.
  method make_sound.
    rv_sound = 'Meow!'.
  endmethod.
endclass.

start-of-selection.
  data: lo_animal         type ref to lcl_animal.

  create object lo_animal type lcl_dog.
  write: / 'Hund bellt:', lo_animal->make_sound( ).

  create object lo_animal type lcl_cat.
  write: / 'Katze miaut:', lo_animal->make_sound( ).

Hier ist nun die Abstract Factory-Methode Anwendung des obigen Abap-Codes.

UML Code:

@startuml

abstract class lcl_animal {
  + make_sound(): string
}

class lcl_dog {
  + make_sound(): string
}

class lcl_cat {
  + make_sound(): string
}

abstract class lcl_animal_factory {
  + create_animal(): lcl_animal
}

class lcl_dog_factory {
  + create_animal(): lcl_animal
}

class lcl_cat_factory {
  + create_animal(): lcl_animal
}

lcl_animal <|-- lcl_dog
lcl_animal <|-- lcl_cat
lcl_animal_factory <|-- lcl_dog_factory
lcl_animal_factory <|-- lcl_cat_factory
lcl_dog_factory ..> lcl_dog
lcl_cat_factory ..> lcl_cat

@enduml

Erstelt mit PlantUML

Erstelt mit PlantUML

class lcl_animal definition abstract.
public section.
  methods: make_sound abstract returning value(rv_sound) type string.
endclass.

class lcl_dog definition inheriting from lcl_animal.
  public section.
    methods: make_sound redefinition.
endclass.

class lcl_cat definition inheriting from lcl_animal.
  public section.
    methods: make_sound redefinition.
endclass.

class lcl_dog implementation.
  method make_sound.
    rv_sound = 'Woof!'.
  endmethod.
endclass.

class lcl_cat implementation.
  method make_sound.
    rv_sound = 'Meow!'.
  endmethod.
endclass.

class lcl_animal_factory definition abstract.
public section.
  methods: create_animal abstract returning value(ro_animal) type ref to lcl_animal.
endclass.

class lcl_dog_factory definition inheriting from lcl_animal_factory.
  public section.
    methods: create_animal redefinition.
endclass.

class lcl_cat_factory definition inheriting from lcl_animal_factory.
  public section.
    methods: create_animal redefinition.
endclass.

class lcl_dog_factory implementation.
  method create_animal.
    create object ro_animal type lcl_dog.
  endmethod.
endclass.

class lcl_cat_factory implementation.
  method create_animal.
    create object ro_animal type lcl_cat.
  endmethod.
endclass.

start-of-selection.
  data: lo_animal_factory type ref to lcl_animal_factory,
        lo_animal         type ref to lcl_animal.

  lo_animal_factory = new lcl_dog_factory( ).
  lo_animal = lo_animal_factory->create_animal( ).
  write: / 'Hund bellt:', lo_animal->make_sound( ).

  lo_animal_factory = new lcl_cat_factory( ).
  lo_animal = lo_animal_factory->create_animal( ).
  write: / 'Katze miaut:', lo_animal->make_sound( ).

Abstrakte Klassen für Tiere (lcl_animal) und Fabriken (lcl_animal_factory):

  • Die abstrakte Klasse lcl_animal definiert eine abstrakte Methode make_sound, die von Unterklassen implementiert werden muss.
  • Die abstrakte Klasse lcl_animal_factory definiert eine abstrakte Methode create_animal, die von Unterklassen implementiert werden muss, um Tierobjekte zu erstellen.

Konkrete Klassen für Hunde (lcl_dog) und Katzen (lcl_cat):

  • Die Klassen lcl_dog und lcl_cat erben von lcl_animal und implementieren die abstrakte Methode make_sound, um das Geräusch des jeweiligen Tiers zurückzugeben.

Konkrete Fabrik-Klassen für Hunde und Katzen (lcl_dog_factory und lcl_cat_factory):

  • Die Klassen lcl_dog_factory und lcl_cat_factory erben von lcl_animal_factory und implementieren die Methode create_animal, um jeweils ein Hund- bzw. Katzenobjekt zu erstellen.

Implementierung der create_animal-Methoden:

  • In den Implementierungen der create_animal-Methoden wird jeweils ein Objekt der entsprechenden Tierklasse erstellt und zurückgegeben.

Verwendung der Fabrikklassen:

  • Im Hauptprogramm werden Objekte der Fabrikklassen erstellt und verwendet, um Tierobjekte zu erstellen.
  • Zuerst wird eine lcl_dog_factory erstellt, um ein Hundeobjekt zu erstellen, und dann wird eine lcl_cat_factory erstellt, um ein Katzenobjekt zu erstellen.

Und jetzt erweitern wir unsere Klasse um laufende Tiere, fliegende Tiere und schwimmende Tiere.

UML Code:

@startuml
abstract class lcl_animal {
  + make_sound() : string
}

class lcl_dog {
  + make_sound() : string
}

class lcl_cat {
  + make_sound() : string
}

class lcl_fish {
  + make_sound() : string
}

abstract class lcl_abstract_factory {
  + create_flying_animal() : lcl_animal
  + create_walking_animal() : lcl_animal
  + create_swimming_animal() : lcl_animal
}

class lcl_animal_factory {
  + create_flying_animal() : lcl_animal
  + create_walking_animal() : lcl_animal
  + create_swimming_animal() : lcl_animal
}

lcl_animal <|-- lcl_dog
lcl_animal <|-- lcl_cat
lcl_animal <|-- lcl_fish
lcl_animal_factory ..> lcl_dog
lcl_animal_factory ..> lcl_cat
lcl_animal_factory ..> lcl_fish
lcl_abstract_factory <|.. lcl_animal_factory
@enduml
class lcl_animal definition abstract.
  public section.
    methods: make_sound abstract returning value(rv_sound) type string.
endclass.

class lcl_dog definition inheriting from lcl_animal.
  public section.
    methods: make_sound redefinition.
endclass.

class lcl_dog implementation.
  method make_sound.
    rv_sound = 'Woof!'.
  endmethod.
endclass.

class lcl_cat definition inheriting from lcl_animal.
  public section.
    methods: make_sound redefinition.
endclass.

class lcl_cat implementation.
  method make_sound.
    rv_sound = 'Meow!'.
  endmethod.
endclass.

class lcl_fish definition inheriting from lcl_animal.
  public section.
    methods: make_sound redefinition.
endclass.

class lcl_fish implementation.
  method make_sound.
    rv_sound = 'Blub!'.
  endmethod.
endclass.

class lcl_abstract_factory definition abstract.
  public section.
    methods:
      create_flying_animal abstract returning value(ro_flying_animal) type ref to lcl_animal,
      create_walking_animal abstract returning value(ro_walking_animal) type ref to lcl_animal,
      create_swimming_animal abstract returning value(ro_swimming_animal) type ref to lcl_animal.
endclass.

class lcl_animal_factory definition inheriting from lcl_abstract_factory.
  public section.
    methods:
      create_flying_animal redefinition,
      create_walking_animal redefinition,
      create_swimming_animal redefinition.
endclass.

class lcl_animal_factory implementation.
  method create_flying_animal.
    create object ro_flying_animal type lcl_cat.
  endmethod.

  method create_walking_animal.
    create object ro_walking_animal type lcl_dog.
  endmethod.

  method create_swimming_animal.
    create object ro_swimming_animal type lcl_fish.
  endmethod.
endclass.

start-of-selection.
  data: lo_factory         type ref to lcl_abstract_factory,
        lo_flying_animal   type ref to lcl_animal,
        lo_walking_animal  type ref to lcl_animal,
        lo_swimming_animal type ref to lcl_animal.

  create object lo_factory type lcl_animal_factory.

  lo_flying_animal = lo_factory->create_flying_animal( ).
  lo_walking_animal = lo_factory->create_walking_animal( ).
  lo_swimming_animal = lo_factory->create_swimming_animal( ).

  write: / lo_flying_animal->make_sound( ),
         / lo_walking_animal->make_sound( ),
         / lo_swimming_animal->make_sound( ).

Das Abstract Factory ist in ABAP eine leistungsfähige Methode, um ohne die spezifischen Klassen zu definieren, eine Familie von zusammengehörigen oder voneinander abhängigen Objekten zu erzeugen. Dieses Entwurfsmuster umfasst einige Schlüsselpunkte und Schlussfolgerungen, darunter die Förderung von Flexibilität und Austauschbarkeit von Objekten, die Möglichkeit zur einfachen Erweiterung um neue Produkte oder Produktfamilien sowie die Trennung von Client-Code und konkreter Implementierung. Dies führt Das Abstract Factory erleichtert außerdem die Umsetzung des Abstraktionsprinzips und gewährleistet eine saubere Trennung zwischen der Objekterzeugung und ihrer Verwendung, was zu einem modularen und besser strukturierten Code führt.


메타데이터
post_id
f2d835ec21af
slug
abap-entwurfsmuster-2-abstract-factory-f2d835ec21af
url
https://medium.com/@urcm/abap-entwurfsmuster-2-abstract-factory-f2d835ec21af
canonical_url
https://medium.com/@urcm/abap-entwurfsmuster-2-abstract-factory-f2d835ec21af
author_url
https://medium.com/@urcm
status
ok
fetched_at
2026-06-20 20:29:01