Absztrakt dokumentum minta

Az absztrakt dokumentum minta egy szerkezeti programtervezési minta, arra, hogy az objektumokat lazán típusozott kulcs-érték szerkezetbe rendezze, amit különböző típusú nézetekkel lehet megnézni. Célja, hogy nagy mértékű hajlékonyságot érjen el egy erősen típusozott nyelvben, ahol az objektumfa menet közben új tulajdonságokkal bővíthető a típusbiztonság támogatásának elvesztése nélkül. A minta vonásokat használ, hogy egy osztály tulajdonságait különböző interfészekbe ossza.[1] A dokumentum szó a dokumentumorientált adatbázisokból származik.

Definíció szerkesztés

A dokumentum egy objektum, ami több különböző tulajdonságot tartalmaz. Ez lehet egy érték, szám vagy string, vagy más dokumentumok listája. Minden tulajdonságot kulccsal hivatkoznak..[2] A dokumentumfa beutazásakor a felhasználó meghatároz egy konstruktort, amivel a következő szint osztályának megvalósítását létrehozza. Ezek gyakran különböző vonások uniója, amelyek a dokumentum (Docemunent) interfészt terjesztik ki, és lehetővé teszik, hogy önállóan kezeljék a tulajdonságok átadását és módosítását.

Szerkezete szerkesztés

 
Absztrakt dokumentum minta szerkezeti vázlata

A Document interfész megállapítja, hogy mely tulajdonságok olvashatók és írhatók get és put metódiusokkal, továbbá az aldokumentumok bejárhatók a children metódussal. Ez függvényreferenciát igényel egy metódusra, ami képes egy gyerek típusozott nézetét generálni annak a mapnek az ismeretében, ami hivatkozza azokat az adatokat, amelyeket a gyereknek tartalmaznia kell. A hivatkozásokra azért van szükség, hogy ha itt megváltoztatnak valamit, akkor az eredeti is megváltozzon.

A megvalósítások több traitből is örökölhetnek, amelyek különböző tulajdonságokat írnak le, habár lehetnek több traitből örökölt tulajdonságok is. Az egyetlen korlátozás az, hogy a megvalósítás állapotmentes legyen, kivéve a BaseDocumentből örökölt tulajdonságokat.

Használata szerkesztés

Az absztrakt dokumentumminta megengedi, hogy a programozó úgy tárolja a változókat, mint konfigurációs változókat egy nem típusozott dokumentumfában, és a dokumentumokat típusozott nézetekben szerkesztheti. Az újabb nézetek vagy megvalósítások nem érintik a belső dokumentumszerkezetet. Ennek az az előnye, hogy lazítja a kapcsolatot az elemek között, de növeli a típuskonverzióból következő hibák valószínűségét, mivel a tulajdonságok típusa nem mindig nyilvánvaló.

Pszeudokód szerkesztés

 interface Document
  put(key : String, value : Object) : Object
   get(key : String) : Object
   children(key : String, constructor : Map<String, Object> -> T) : T[]
   
 abstract class BaseDocument : Document
   properties : Map<String, Object>
   
   constructor(properties : Map<String, Object>)
       this->properties := properties
       
   implement put(key : String, value : Object) : Object
       return this->properties->put(key, value)
       
   implement get(key : String) : Object
       return this->properties->get(key)
       
   implement children(key : String, constructor : Map<String, Object> -> T) : T[]
       var result := new T[]
       
       var children := this->properties->get(key) castTo Map<String, Object>[]
       foreach ( child in children )
           result[] := constructor->apply(child)
           
       return result

Implementációs példa szerkesztés

A következő példák Java nyelvűek.

Document.java

public interface Document {
    Object put(String key, Object value);
    Object get(String key);
    <T> Stream<T> children(
            String key,
            Function<Map<String, Object>, T> constructor
    );
}

BaseDocument.java

public abstract class BaseDocument implements Document {
    private final Map<String, Object> entries;
    protected BaseDocument(Map<String, Object> entries) {
        this.entries = requireNonNull(entries);
    }
    @Override
    public final Object put(String key, Object value) {
        return entries.put(key, value);
    }
    @Override
    public final Object get(String key) {
        return entries.get(key);
    }
    @Override
    public final <T> Stream<T> children(
            String key,
            Function<Map<String, Object>, T> constructor) {
        final List<Map<String, Object>> children = 
            (List<Map<String, Object>>) get(key);
        return children == null
                    ? Stream.empty()
                    : children.stream().map(constructor);
    }
}

Usage.java

Map<String, Object> source = ...;
Car car = new Car(source);
String model = car.getModel();
int price = car.getPrice();
List<Wheel> wheels = car.children("wheel", Wheel::new)
    .collect(Collections.toList());

Jegyzetek szerkesztés

  1. Forslund, Emil: Age of Java: The Best of Both Worlds. Ageofjava.blogspot.com , 2016. január 15. [2016. január 18-i dátummal az eredetiből archiválva]. (Hozzáférés: 2016. január 23.)
  2. Fowler, Martin: Dealing with Properties. (Hozzáférés: 2016. január 29.)

Fordítás szerkesztés

Ez a szócikk részben vagy egészben az Abstract Document Pattern című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.