Bileşik desen birden fazla yaprak şekli bir sorun

2 Cevap java

Işte, biz daha sonra Java içine yeniden programlanmış olacak bir PHP uygulama geliştiriyoruz. Java bazı temel bilgi ile, herhangi bir baş ağrısı olmadan, her şeyi kolayca yeniden yazılması için tasarım için çalışıyoruz. Biz yapraklar yöntemlerin büyük sayıda composite pattern uygulamaya çalıştığımızda ilginç bir sorun çıktı.

Ne biz (arayüzleri kullanarak değil, sadece hızlı bir örnek) elde etmek için çalışıyoruz:

class Composite {
    ...
}


class LeafOne {
    public function Foo( );

    public function Moo( );
}


class LeafTwo {
    public function Bar( );

    public function Baz( );
}


$c = new Composite( Array( new LeafOne( ), new LeafTwo( ) ) );

// will call method Foo in all classes in composite that contain this method
$c->Foo( );

// same with Bar
$c->Bar( );

It seems like pretty much classic Composite pattern, but problem is that we will have quite many leaf classes and each of them might have ~5 methods (of which few might be different than others). One of our solutions, which seems to be the best one so far and might actually work, is using __call magic method to call methods in leafs. Unfortunately, we don't know if there is an equivalent of it in Java.

Yani asıl soru şudur: Bu iyi bir çözüm sonunda kolayca Java içine yeniden kodlanmış olacaktır kodu kullanarak, var mı? Yoksa başka bir çözüm önerirsiniz? Belki burada kullanabilirsiniz bazı farklı, daha iyi bir desen var.

Durumda belirsiz bir şey var, sadece isteyin ve ben bu yazıyı düzenlemek edeceğiz.

Edit:

Gerçek sorun, her yaprak sınıf içerir değil, örneğin, yöntem Baz. Her sınıfta Baz aramak için basit bir foreach kullandıysanız, bu yöntemi içermeyen bazı sınıflar vardır gibi, kullanım hataları demet verirdim. Klasik çözüm her yaprak sınıftan itibaren her yöntem farklı uygulama ile her biri, Kompozit sınıfa uygulanan sahip olacaktır. Ama bu bizim birleşik sınıf büyük ve kullandığımız yöntemleri miktarda dağınık olur.

Yani olağan çözüm Bu gibi (Kompozit sınıf) görünecektir:

class Composite implements Fooable, Bazable {
    ...

    public function Foo( ) {
        foreach( $this->classes as $class ) {
            $class->Foo( );
        }
    }

    public function Baz( ) {
        ...
    }
}

Gerçek karmaşa haline bizim kod önlemek için, biz böyle bir şey düşünüyorduk:

class Composite {
    ...

    public function __call( ) {
        // implementation
    }
}

Ama biz iyi bir çözüm eğer gerçekten emin değilseniz ve (düzenlemeden önce zaten sorulmuş gibi) Java da benzer bir şey varsa.

2 Cevap

Java içinde size ağaçtaki her düğüm için bir ziyaretçi nesnesi geçirmek ve düğüm yapılmalıdır hangi davranışı belirlemek için ziyaretçi sınıfının bir callback yapar sayede visitor desen kullanmayı düşünebiliriz .

Bu herhangi bir döküm kaçınır ya da açıkça her düğümün türünü kontrol.

/**
 * Visitor capable of visiting each node within a document.
 * The visitor contains a callback method for each node type
 * within the document.
 */
public interface DocumentNodeVisitor {
  void visitWord(Word word);
  void visitImage(Image img);
}

/**
 * Base interface for each node in a document.
 */
public interface DocumentNode {
  void applyVisitor(DocumentVisitor v);
}

/**
 * Conrete node implementation representing a word.
 */    
public class Word implements DocumentNode {
  private final String s;

  public Word(String s) { this.s = s; }

  public String getValue() { return this.s; }

  public void applyVisitor(DocumentVisitor v) {
    // Make appropriate callback to visitor.
    v.visitWord(this);
  }
}

/**
 * Conrete node implementation representing an image.
 */        
public class Image implements DocumentNode {
  public void applyVisitor(DocumentVisitor v) {
    // Make appropriate callback to visitor.
    v.visitImage(this);
  }
}

public class Paragraph implements DocumentNode {
  private final List<DocumentNode> children;

  public Paragraph() {
    this.children = new LinkedList<DocumentNode>();
  }

  public void addChild(DocumentNode child) {
    // Technically a Paragraph should not contain other Paragraphs but
    // we allow it for this simple example.
    this.children.add(child);
  }

  // Unlike leaf nodes a Paragraph doesn't callback to
  // the visitor but rather passes the visitor to each
  // child node.
  public void applyVisitor(DocumentVisitor v) {
    for (DocumentNode child : children) {
      child.applyVisitor(v);
    }
  }
}    

/**
 * Concrete DocumentVisitor responsible for spell-checking.
 */
public class SpellChecker implements DocumentVisitor
  public void visitImage(Image i) {
    // Do nothing, as obviously we can't spellcheck an image.
  }

  public void visitWord(Word word) {
    if (!dictionary.contains(word.getValue()) {
      // TODO: Raise warning.
    }
  }
}

Ziyaretçi tasarım deseni oldukça iyi bir çözümdür. Ama yapısında muhtemel değişiklikler, örneğin göz önünde bulundurmanız gerekir Yeni Yaprak sınıfı applyVisitor uygulamak ve oluşturduğunuz her Ziyaretçi ziyaretini * yöntem eklemek yapacaktır. Yani Ziyaretçi gerçekten bu yapı çok sık değişen değil fiyata yapılandırılmış nesnelere davranış eklemek için helpts. Yapısı genellikle değiştirir ve algoritmaları çok değil ise, aynı arayüzleri ile nesneler için farklı kompozit sahip düşünebilirsiniz. Bunu dirty şekilde yapmak istiyorsanız şu anda PHP gibi, Java yansıma API bakmak. Güzel bir çözüm (Ruby veya Python gibi) imho dinamik çağrılar olacaktır. O taklit edebilirsiniz, ama bu kadar iş olurdu ... Yani benim cevap dikkatle Ziyaretçi kullanabilir veya farklı davranışları ile nesneler için farklı kompozitler düşünün.