Quale pattern usa, oggetto con sottotipi solo proprietà differenti

0

Ho una semplice notifica di classe, che ha alcune proprietà (titolo, corpo, op) e solo getter / setter. Tra tutti i miei progetti userò diversi tipi di notifiche, questo è oggetti di notifica ma con titolo, corpo, op diversi a seconda della logica di quella parte.

Mi chiedo quale sarebbe l'apice migliore per implementarlo. Ho pensato di usare un qualche tipo di polimorfismo che avrebbe funzionato, ma non sono sicuro che sarebbe stato un overcoding. Ecco la notifica della classe:

<?php

namespace App\Library\Notifications;

/**
 * Class Notification
 */
class Notification
{
    /** @var string $title*/
    private $title;
    /** @var string $body */
    private $body;
    /** @var string $op */
    private $op;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->title = '';
        $this->body = '';
        $this->op = '';
    }

    public function getTitle(): string
    {
        return $this->title;
    }

    public function getBody(): string
    {
        return $this->body;
    }

    /**
     * String that tells the apps which kind of notification
     * we are sending so they can act depending of the type
     *
     * @return string
     */
    public function getOp(): string
    {
        return $this->op;
    }

}

Ed ecco una sottoclasse:

<?php

namespace App\Library\Notifications;

use Illuminate\Support\Facades\Lang;

/**
 * Class Notification
 */
class OtherAcceptedTripNotification extends Notification
{
    /**
     * Constructor
     */
    public function __construct()
    {
        parent::__construct();

        $this->title = Lang::get('notifications.other_accepted_trip_title');
        $this->body = Lang::get('notifications.other_accepted_trip_body');
        $this->op = 'OA';
    }
}
    
posta vivoconunxino 28.06.2018 - 16:07
fonte

2 risposte

4

È un'eredità che abusa.

Una classe ereditata viene usata quando cambia qualcosa sulla classe base (ma mantiene parte della logica della classe base esistente).

Nel tuo esempio, nulla è cambiato tranne il valore delle proprietà. Non stai aggiungendo / modificando alcun comportamento logico.

Questo è effettivamente lo stesso di fare (perdona la sintassi C #):

public class Person()
{
    public string Name { get; set; }

    public Person(string name)
    {
        this.Name = name;
    }
}

public class John : Person
{
    public John() : base("John") {}
}

public class Bob : Person
{
    public Bob() : base("Bob") {}
}

public class Tom : Person
{
    public Tom() : base("Tom") {}
}

O, ancora più sfacciatamente:

public class MyNumberClass()
{
    public int Value { get; set; }

    public MyNumberClass(int value)
    {
        this.Value = value;
    }
}

public class Five : MyNumberClass
{
    public Five() : base(5) {}
}

public class Twenty : Person
{
    public Twenty() : base(20) {}
}

Questo non è ciò per cui viene usata l'ereditarietà! Dovresti utilizzare semplici variabili qui:

var myAge = new MyNumberClass(20);

var myBoss = new Person("Bob");

var otherAcceptedTripNotification = new Notification ("title", "body", "op");

Il modello di fabbrica.

Tuttavia, capisco la tua intenzione qui. Stai provando a creare un predefinito predefinito, in modo da non dover utilizzare valori con hardcoded. Se si utilizza lo stesso tipo OtherAcceptedTripNotification sulla base di codice, non si desidera ripetersi.

Questo è un problema reale che vale la pena risolvere. Il pattern factory è una buona soluzione qui .

Il riferimento collegato (e altre risorse online) sono molto dettagliate e, a mio parere, molto complesse. Per ridurlo all'esempio più barebone per illustrare il punto (ancora, perdonare il C #):

public static class NotificationFactory
{
    public static Notification CreateOtherAcceptedTripNotification(string bodyText)
    {
        return new Notification(
                      "THIS HEADER CANNOT BE CHANGED",
                      "FIXED PREFIX : " + bodyText,
                      "FIXED OA"
                    );
    }
}

Questo ti dà il beneficio che vuoi (solo bisogno di definire i valori fissi di una notifica "preset" una sola volta) senza lo svantaggio (abuso di ereditarietà).

    
risposta data 28.06.2018 - 16:56
fonte
2

In questo caso è possibile utilizzare una fabbrica o disporre di un set creato e accessibile per nome. Il mio pseudo-codice non è la stessa lingua che stai usando, ma puoi adattare il modello.

public class Notification {
    internal Notification(string title, string body, string op) {
        Title = title;
        Body = body;
        Op = op;
    }

    public string Title { get; private set; }
    public string Body { get; private set; }
    public string Op { get; private set; }
}

public static class Notifications {
    public static Notification OtherAcceptedTrip = new Notification(
        Lang.Get("notifications.other_accepted_trip_title"),
        Lang::get("notifications.other_accepted_trip_body"),
        "OA");
}

A questo punto, puoi usare quella notifica ogni volta che vuoi proprio così:

SendNotification( Notifications.OtherAcceptedTrip );

In sostanza, stai controllando le istanze della notifica. Se non puoi riutilizzare la stessa istanza dappertutto perché l'oggetto Notification sta facendo altre cose oltre a ciò che hai elencato qui, useresti una factory. La factory creerà un'istanza dell'oggetto Notification con i giusti valori che è possibile utilizzare e non sarà condivisa con nessun altro.

    
risposta data 28.06.2018 - 16:55
fonte

Leggi altre domande sui tag