Composite, Iterateur et Visiteur

/*
* ENSICAEN, École publique d'ingénieurs et centres de recherche, Caen, FRANCE.
* https://www.ensicaen.fr
*
* This file is licenced under the MIT License.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package fr.ensicaen.gl2a.lecture.composite;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Composite {

public static void main( String[] args ) {
Forme tete = new Oux(new Sphere(1, 10), new Oux(new Sphere(2, 5), new Sphere(3, 5))); // Yeux
Forme bonhomme = new Et(tete,
new Et(new Cube(4, 50),
new Et(new Cylindre(5, 5, 10), new Cylindre(6, 5, 10), new Cylindre(7, 15, 50), new Cylindre(8, 15, 50))));
// Test composite
System.out.println("Dessin du bonhomme");
bonhomme.dessiner();

// Test Iterateur
System.out.print("Liste des formes primitives de bonhomme : ");
Iterator<Forme> iterator4 = bonhomme.iterator();
while (iterator4.hasNext()) {
Forme f = iterator4.next();
System.out.print(f + ", ");
}
System.out.println();

// ou plus classiquement
System.out.print("Variante : Liste des formes primitives de bonhomme : ");
for (Forme f : bonhomme) {
System.out.print(f + ", ");
}
System.out.println();

// Test visiteur
double aire = (double) bonhomme.accepte(new Aire());
System.out.println("Aire du bonhomme=" + aire);
}
}

abstract class Forme implements Iterable<Forme> {

public abstract Iterator<Forme> iterator();

public abstract void dessiner();

public abstract Object accepte( Visiteur visiteur );
}

final class Cube extends Forme {
private final int _index;
private final float _size;

public Cube( int index, float size ) {
_index = index;
_size = size;
}

public float getSize() {
return _size;
}

@Override
public void dessiner() {
System.out.println("Je dessiner " + this);
}

@Override
public String toString() {
return "Cube n°" + _index;
}

@Override
public Iterator<Forme> iterator() {
return new IterateurSimple(this);
}

public Object accepte( Visiteur visiteur ) {
return visiteur.visite(this);
}
}

final class Sphere extends Forme {
private final int _index;
public float _rayon;

public Sphere( int index, float rayon ) {
_index = index;
_rayon = rayon;
}

public float getRayon() {
return _rayon;
}

@Override
public void dessiner() {
System.out.println("Je dessiner " + this);
}

@Override
public String toString() {
return "Cylindre n°" + _index;
}

@Override
public Iterator<Forme> iterator() {
return new IterateurSimple(this);
}

@Override
public Object accepte( Visiteur v ) {
return v.visite(this);
}
}

final class Cylindre extends Forme {
public final float _rayon;
public final float _hauteur;
private final int _index;

public Cylindre( int index, float rayon, float hauteur ) {
_index = index;
_rayon = rayon;
_hauteur = hauteur;
}

@Override
public void dessiner() {
System.out.println("Je dessiner " + this);
}

@Override
public String toString() {
return "Cylindre n°" + _index;
}


@Override
public Object accepte( Visiteur v ) {
return v.visite(this);
}

@Override
public Iterator<Forme> iterator() {
return new IterateurSimple(this);
}

public float getRayon() {
return _rayon;
}

public float getHauteur() {
return _hauteur;
}
}

abstract class FormeComplexe extends Forme {
private final Forme[] _composants;

public FormeComplexe( Forme... formes ) {
_composants = formes;
}

public Forme[] getComposants() {
return _composants;
}

@Override
public Iterator<Forme> iterator() {
return new IterateurComplexe(this);
}
}

final class Et extends FormeComplexe {
public Et( Forme... formes ) {
super(formes);
}

@Override
public void dessiner() {
for (Forme f : getComposants()) {
f.dessiner();
}
}

public Object accepte( Visiteur visiteur ) {
return visiteur.visite(this);
}

}

final class Oux extends FormeComplexe {
public Oux( Forme... formes ) {
super(formes);
}

@Override
public void dessiner() {
for (Forme f : getComposants()) {
f.dessiner();
}
}

public Object accepte( Visiteur visiteur ) {
return visiteur.visite(this);
}
}

//
// Iterateur
//
class IterateurSimple implements Iterator<Forme> {
private final Forme _forme;
private boolean _next = true;

public IterateurSimple( Forme forme ) {
_forme = forme;
}

@Override
public boolean hasNext() {
return _next;
}

@Override
public Forme next() {
_next = false;
return _forme;
}
}

final class IterateurComplexe implements Iterator<Forme> {
private final Iterator<Forme>[] _iterators;

public IterateurComplexe( FormeComplexe forme ) {
Forme[] composants = forme.getComposants();
_iterators = new Iterator[composants.length];
for (int i = 0; i < composants.length; i++) {
_iterators[i] = composants[i].iterator();
}
}

@Override
public boolean hasNext() {
for (Iterator<Forme> iterator : _iterators) {
if (iterator.hasNext()) {
return true;
}
}
return false;
}

@Override
public Forme next() {
for (Iterator<Forme> iterator : _iterators) {
if (iterator.hasNext()) {
return iterator.next();
}
}
throw new NoSuchElementException();
}
}

//
// Visiteur
//
abstract class Visiteur {
public abstract Object visite( Sphere s );

public abstract Object visite( Cube formes );

public abstract Object visite( Cylindre formes );

public abstract Object visite( Et formes );

public abstract Object visite( Oux formes );
}

final class Aire extends Visiteur {
@Override
public Object visite( Cube cube ) {
return Math.pow(cube.getSize(), 3);
}

@Override
public Object visite( Sphere sphere ) {
return 3 * Math.PI * Math.pow(sphere.getRayon(), 3);
}

@Override
public Object visite( Cylindre cylindre ) {
return 2 * Math.PI * Math.pow(cylindre.getRayon(), 2) * cylindre.getHauteur();
}

@Override
public Object visite( Et et ) {
Forme[] composants = et.getComposants();
double total=0;
for (Forme composant : composants) {
total += (double) composant.accepte(this);
}
return total;
}

@Override
public Object visite( Oux oux ) {
Forme[] composants = oux.getComposants();
int sign=1;
double total=0;
for (Forme composant : composants) {
total = sign * (double) composant.accepte(this);
sign = 1 - sign;
}
return total;
}
}

Last modified: Saturday, 19 September 2020, 12:30 PM