Visitor

Um problema a resolver

O padrão Visitor

Objetivo

Resumo

Quando usar o padrão Visitor?

Estrutura genérica

Participantes

Colaborações

Conseqüências do padrão Visitor

Considerações de implementação

Exemplo de código

ublic interface Element extends Comparable {
  // composite design pattern being used

  public final int TYPE_UNDEFINED = 0;
  public final int TYPE_BREAKER = 1;
  public final int TYPE_RECLOSER = 2;
  public final int TYPE_SWITCH = 3;
  public final int TYPE_SUBSTATION = 4;
  public final int TYPE_TRANSFORMER = 5;
  public final int TYPE_LINE = 6;
  public final int TYPE_STATIC_COMPENSATOR = 7;
  public final int TYPE_GENERATOR = 8;
  public final int TYPE_SYNCHRONOUS_COMPENSATOR = 9;
  public final int TYPE_BUS = 10;
  public final int TYPE_PHANTOM_BUS = 11;
  public final int TYPE_REACTOR = 12;
  public final int TYPE_CAPACITOR_BANK = 13;
  public final int TYPE_REGION = 14;

  public final int SUBTYPE_UNDEFINED = 0;
  public final int SUBTYPE_BREAKER_REACTOR = 1;
  public final int SUBTYPE_BREAKER_LINE = 2;
  public final int SUBTYPE_BREAKER_TRANSFORMER = 3;
  public final int SUBTYPE_BREAKER_CENTRAL = 4;
  public final int SUBTYPE_BREAKER_TRANSFER_1 = 5;
  public final int SUBTYPE_BREAKER_TRANSFER_2 = 6;
  public final int SUBTYPE_BREAKER_SYNCHRONOUS_COMPENSATOR = 7;
  public final int SUBTYPE_BREAKER_CAPACITOR_BANK = 8;
  public final int SUBTYPE_REGION_SYSTEM = 9;
  public final int SUBTYPE_REGION_REGIONAL_CENTER = 10;
  public final int SUBTYPE_BUS_1 = 11;
  public final int SUBTYPE_BUS_2 = 12;

  // ...

  public void accept(Visitor visitor) throws Exception;
  // ...
}

public class Region extends AbstractElement {
  // ...
  public void accept(Visitor visitor) throws Exception {
    visitor.visitRegion(this);
    Iterator it = getSortedSubRegionsIterator();
    while(it.hasNext()) {
      Element subregion = (Element)it.next();
      subregion.accept(visitor);
    }
  }
}

public class Device extends ElementTwoNodes {
  // ...
  public void accept(Visitor visitor) throws Exception {
    visitor.visitDevice(this);
  }
}

public class Breaker extends Device {
  // ...
  public void accept(Visitor visitor) throws Exception {
    visitor.visitBreaker(this);
  }
}
// ...
public class Convert {
  private static Convert instance = null;
  private Properties substationNameToCentersMap;
  private Map allElements = new HashMap();
  private Map substationIdToCentersMap = new HashMap();

  public static void main(String[] args) {
    configLog();
    if(args.length != 2) {
      syntax();
    }
    try {
      Region theWholeThing = Convert.getInstance().solve(args[0], args[1]);
      System.out.println(theWholeThing.toXml());
    } catch (Exception ex) {
      logger.error("Excecao: " + ex.toString());
    }
  }

  private Region solve(String dataFileName, String substationFileName) 
         throws Exception {
    // create an object structure
    Region theWholeThing = load(dataFileName, substationFileName);
    classify(theWholeThing);
    removeLinesOutsideARegion(theWholeThing);
    removeLineReferences(theWholeThing);
    audit(theWholeThing);
    return theWholeThing;
  }

  private void classify(Region topRegion) throws Exception {
    topRegion.accept(new ClassifierVisitor());
  }

  public void removeLinesOutsideARegion(Region topRegion) throws Exception {
    topRegion.accept(new RemoveElementsOutsideARegionVisitor("CROL"));
  }

  public void removeLineReferences(Region topRegion) throws Exception {
    topRegion.accept(new RemoveLineReferencesVisitor());
  }

  private void audit(Region topRegion) throws Exception {
    topRegion.accept(new AuditVisitor());
  }

  // ...
}
public interface Visitor {
  public void visitBreaker(Element element) throws Exception;
  public void visitDevice(Element element) throws Exception;
  public void visitRegion(Element element) throws Exception;
  public void visitReactor(Element element) throws Exception;
  public void visitLine(Element element) throws Exception;
}

public abstract class AbstractVisitor implements Visitor {
  public void visitLine(Element element) throws Exception {}
  public void visitReactor(Element element) throws Exception {}
  public void visitDevice(Element element) throws Exception {}
  public void visitRegion(Element element) throws Exception {}
  public void visitBreaker(Element element) throws Exception {}
}

public class AuditVisitor extends AbstractVisitor {
  static Logger logger = Logger.getLogger(AuditVisitor.class.getName());

  public void visitBreaker(Element element) {
    if(!element.acceptableElement()) {
      return;
    }
    if(element.getAssociatedLine() == null &&
       element.getAssociatedTransformer() == null) {
      logger.info(element.getTypeName() + " " + element.getId() +
                  " nao foi associado a uma regra de linha/transformador");
    }
  }

  public void visitReactor(Element element) {
    if(!element.acceptableElement()) {
      return;
    }
    if(element.getAssociatedLine() == null) {
      logger.info(element.getTypeName() + " " + element.getId() +
                  " nao foi associado a uma regra de linha");
    }
  }
  public void visitLine(Element element) {
    if(!element.acceptableElement()) {
      return;
    }
    if(element.getAssociatedBreaker1() == null) {
      logger.info(element.getTypeName() + " " + element.getId() +
                  " nao tem disjuntor de linha");
    }
  }
}

// etc. para outros Visitors

Pergunta final para discussão

programa