Come memorizzare più requisiti con OR e AND?

2

Bene, sto lavorando a un progetto personale che deve verificare se un utente ha soddisfatto determinati requisiti e si presenta sotto forma di

Requisito: [c1 OR c2] AND [d1 OR d2]

Requisito: [c1 AND c2] OR [d1 AND d2]

Requisito: c1 AND any dn (n può essere qualsiasi intero)

Non sono sicuro di come archiviare questo tipo di requisiti, sto pensando di usare un altro oggetto per contenere c1, c2, d1, d2 .... dn e OR, ma sembra un modo indiretto di facendo cose. C'è un metodo migliore?

    
posta Cano 16.06.2012 - 02:57
fonte

4 risposte

6

Tipicamente, le espressioni sono rappresentate da alberi di sintassi astratti.

public interface Expression {};
public class AND implements Expression {
    public Expression lhs;
    public Expression rhs;
}
public class OR implements Expression {
    public Expression lhs;
    public Expression rhs;
}
public class Requirement implements Expression {
    ...
}
    
risposta data 16.06.2012 - 11:24
fonte
2

Puoi utilizzare Notazione polacca inversa per archiviare e valutare i tuoi requisiti. Per il tuo primo requisito, la sequenza è fondamentalmente:

c1 c2 OR d1 d2 OR AND

Come vedi non hai bisogno di parentesi, quindi il formato di archiviazione è semplice. La valutazione è anche molto facile da implementare, è sufficiente un oggetto stack per inviare i valori dei parametri ei risultati binari nello stack e per eseguire il pop e valutare i parametri quando viene raggiunto un operatore.

    
risposta data 16.06.2012 - 11:19
fonte
1

IOFileFilter e le sue sottoclassi ( ad esempio, AndFileFilter , NotFileFilter e OrFileFilter )  in Apache Commons IO potrebbe essere un buon esempio.

    
risposta data 16.06.2012 - 12:02
fonte
1

Pensa a [c1 OR c2] AND [d1 OR d2] come un singolo requisito. Considera c1, c2, d1, d2 come requisiti, diciamo requisiti secondari o requisiti atomici. Ora hanno tutti una cosa in comune. Possono essere controllati se sono soddisfatti. Quindi introduciamo un'interfaccia per questo:

public interface Requirement {
    public boolean isMet();
}

Ora i requisiti atomici possono essere implementati come

public class AtomicRequirement implements Requirement {
    private final boolean met;

    public AtomicRequirement(boolean isMet) {
        this.met = isMet;
    }

    public boolean isMet() {
        return true;
    }
}

È possibile aggiungere requisiti composti e creare un'interfaccia Requisito.

public class AndRequirement implements Requirement {
    private final Requirement r1, r2;

    public AndRequirement(Requirement r1, Requirement r2) {
        this.r1 = r1;
        this.r2 = r2;
    }

    public boolean isMet() {
        return r1.isMet() && r2.isMet();
    }
}

Lo stesso vale per OR. Puoi farlo con combinatori più complessi

public class AnyOfTheseRequirement implements Requirement {
    private final List<Requirement> anyOfThese;

    public AnyOfTheseRequirement(List<Requirement> anyOfThese) {
        this.anyOfThese = anyOfThese;
    }

    public boolean isMet() {
        for (Requirement r : anyofThese) {
            if (r.isMet()) return true;
        }
        return false;
    }

}

e, naturalmente

public class MakseeRequirement implements Requirement {
    private final AndRequirement r;

    public MakseeRequirement(Requirement c1, List<Requirement> dns) {
        AnyOfTheseRequirement d = new AnyOfTheseRequirement(dns);
        this.r = new AndRequirement(c1, d);
    }

    public boolean isMet() {
        return r.isMet();
    }

}

Questo approccio è abbastanza estensibile, ma puoi ridurlo ai tre tipi effettivi di requisiti che hai ottenuto.

    
risposta data 17.06.2012 - 13:59
fonte

Leggi altre domande sui tag