Schema / Motivo di progettazione per consentire a una determinata classe esterna di impostare le proprietà

5

Ho trovato una soluzione (in PHP) per un problema e mi sto chiedendo se si tratta di un Design Pattern nominato, e se è una buona pratica.

Ho una classe di raccolta e una classe di oggetti. La classe di raccolta è l'unica autorizzata a impostare i dati protetti della classe dell'articolo, oltre alla classe stessa.

L'ho fatto dando alla classe item un metodo che considera l'oggetto collection come argomento. L'oggetto item imposta quindi i suoi dati con gli oggetti collection .

In questo modo, possiamo dire:

$item_coll = new collection();
$item_coll->load($criterion1, $criterion2);

Poiché la raccolta implementa IteratorAggregate, possiamo anche fare questo:

foreach($item_coll as $item) {
  echo 'Item name is ' . $item->getName();
}

Anche dopo aver caricato una raccolta, puoi ottenere una sottocartella utilizzando il metodo getBy($property,$value) :

$sub_collection = $item_coll->getBy('color','green'); // new collection object with green items

E ora ho una collezione di item oggetti con tutti i loro set di dati. Ecco le classi (con metodi / proprietà impertinenti non mostrate).

class item {
  protected $id; // id from database table
  protected $prop1; // properties also from database
  protected $prop2;

  public function setData(collection $coll, $id) {
    $data = $coll->getData($id);
    foreach($data as $key=>$value) {
      $this->$key = $value
    }
    return $this;
  }
  public function getId() {
    return $this->id;
  }
}

class collection implements IteratorAggregate { // interface for foreach access to $collection
    protected $data = array();
    protected $collection = array(); // contains 'item' objects
    public function getData($id) {
      if(array_key_exists($id,$this->data) ) {
        return $this->data[$id];
      } else return array();
    }
    public function load(someClass $obj1, someClass2 $obj2) { // arguments not relevant here, they determine the contents of the collection
      // based on arguments, data is loaded from database into $this->data;
      foreach($rows as $row) { // database data
        $this->data[$id] = $row;
        $obj = $this->collection[$id] = new item();
        $obj->setData($this,$id); // collection object passes itself into item object
      }
    }
    public function html() {//
      foreach($this as $obj) {
        // loop through collection to create an html table for display
      }
    }
    public function addItem(item $item) { // add already-existing items to collection
      if(!array_key_exists($id,$this->collection) ) {
        $this->collection[$item->getId()] = $item;
      }
    }
    public function getIterator() { // for IteratorAggregate interface
      return new ArrayIterator($this->collection);
    }
    public function getBy($property,$value) {
      $collection = new static(); // new collection created
      // loop through $this object and fill $collection with matching item objects
      return $collection;
    }
    public function getById($id) { // get a single item object by its id
      if(array_key_exists($id,$this->collection) ) {
        return $this->collection[$id];
      }
    }
}
    
posta Buttle Butkus 25.02.2015 - 05:56
fonte

3 risposte

1

Penso che stiate provando a usare l'iniezione di dipendenza ma il codice non è facilmente leggibile. Potresti aver usato tre classi invece di due:

  1. Raccolta: per contenere gli oggetti; infatti potresti semplicemente usare un semplice array
  2. Voce
  3. ItemDataManager: per caricare e memorizzare in cache i dati dal DB in modo efficiente.

Con questo approccio il tuo codice sarebbe:

$idm = new ItemDataManager();
$idm->load(criterion1, criterion2);

E quindi potresti passare $ idm come parametro a $ item- > setData. In questo modo ottieni una netta separazione dei compiti tra la gestione delle collezioni e la gestione dei dati ...

    
risposta data 04.03.2015 - 14:14
fonte
1

Il modello a cui ti riferisci è chiamato Iniezione di dipendenza

Fondamentalmente, nella maggior parte dei casi, l'applicazione richiama la libreria / l'oggetto per le informazioni di cui ha bisogno, ma in alcuni casi, l'oggetto deve prima essere configurato con quale dovrebbe servire l'applicazione. Ma se un oggetto generico assume o ottiene da una posizione codificata (ad esempio file di configurazione, ecc.), Allora non è riutilizzabile nel contesto di un'altra applicazione. Quindi, l'oggetto libreria è dipendente indietro sull'applicazione per fornire queste informazioni. La creazione dell'API in una libreria / oggetto in cui l'applicazione fa avanzare le informazioni è denominata Iniezione di dipendenza .

Ci sono tre modi principali per esercitare l'iniezione di dipendenza:

  1. Metodo di costruzione: dove vengono forniti i parametri al momento della chiamata del costruttore.
  2. Metodo setter: dove il metodo standard get / set fa il lavoro.
  3. Metodo di interfaccia: in cui un metodo dedicato viene utilizzato dall'applicazione per passare le informazioni.

Il metodo -load() è essenzialmente l'esempio del metodo di interfaccia che è in grado di fornire più valori e oggetti complessi in un colpo solo.

Leggi questo articolo di Martin Fowler che ti darà una grande prospettiva su questo argomento.

    
risposta data 14.07.2015 - 18:48
fonte
0

Questo sembra più simile al Pattern visitatori , sebbene il controllo potrebbe essere invertito. In realtà direi che non ci sono schemi qui, solo alcuni problemi architettonici.

Hai una classe collection che carica i dati dal database. Esiste un modello di progettazione che descrive questo tipo di comportamento, in cui si ha un archivio dati (non necessariamente un database) e un oggetto che rappresenta la "raccolta" di oggetti memorizzati: il Pattern di repository .

Con pochissime eccezioni, nessun oggetto al di fuori della gerarchia di classi di item dovrebbe accedere ai dati protetti. Al contrario, devi esporre i metodi pubblici per impostare tali dati o richiedere che tali valori vengano passati al costruttore dell'oggetto.

L'utilizzo del modello di repository insieme a un'incapsulazione corretta renderà la tua domanda originale discutibile.

    
risposta data 10.03.2016 - 22:32
fonte

Leggi altre domande sui tag