Tasarım desen soru: kapsülleme veya miras

2 Cevap php

Ben uzunca bir süre üzerinde emekçi olan bir sorum var. I Img.php ve String.php gibi uzantılı sınıfların bir grup ile, iki ana sınıfları Template.php ve Tag.php ile çiftleşmiş motoru inşa ediyorum.

The program works like this:

Bir Şablon nesnesi Tag nesneleri oluşturur. Her bir etiket nesnesi uygulamak için hangi uzatma sınıf (img, string, vb) belirler.

Tag class gibi her bir uzatma sınıf için yardımcı fonksiyonları sağlamak için wrap('div'), addClass('slideshow'), vb nokta

Her Img or String class gerekli olana özel kodu işlemek için kullanılır, bu yüzden $Img->render() gibi bir şey vermek istiyorum <img src='blah.jpg' />

My Question is:

Gerektiği şöyle Etiket nesne içindeki I encapsulate tüm uzatma işlevsellik:

Tag.php

function __construct($namespace, $args) {
    // Sort out namespace to determine which extension to call
    $this->extension = new $namespace($this); // Pass in Tag object so it can be used within extension

    return $this; // Tag object
}

function render() {
    return $this->extension->render();
}

Img.php

    function __construct(Tag $T) {
        $args = $T->getArgs();
        $T->addClass('img');
    }

    function render() {
        return '<img src="blah.jpg" />';
    }

Usage:

$T = new Tag("img", array(...);
$T->render();

"Img bir etiket olan" çünkü .... ya da ben bir inheritance yapısının daha oluşturmanız gerekir

Tag.php

public static create($namespace, $args) {
    // Sort out namespace to determine which extension to call
    return new $namespace($args);

}

Img.php

class Img extends Tag {
    function __construct($args) {
        // Determine namespace then call create tag
        $T = parent::__construct($namespace, $args);
    }

    function render() {
        return '<img src="blah.jpg" />';
    }
}

Usage:

$Img = Tag::create('img', array(...));
$Img->render();

Ben ihtiyacım var tek şey özel etiketler oluşturmak için ortak bir arayüz, yani I (...) IMG örneğini daha sonra String (...) örneğini, ben Tag kullanarak her uzantısı örneğini gerekiyor.

EDIT: Ayrıca sadece açıklama için: Etiket sınıfı tüm uzatma sınıfları için ortak özelliğe sahiptir, uzatma sınıflarında uygulanması gereken Tag sınıfında herhangi bir yöntemleri var olmamalıdır. Etiket sınıfı yalnızca yardımcı fonksiyonları sağlar.

Ben bu sorunun biraz belirsiz olduğunu biliyorum, sana biraz geçmişte bu ele ve her tasarım deseni seçimi ile ilgili belirli konuların öngörebiliriz umuyorum. Eğer başka önerileriniz varsa onları duymak isterim.

Thanks! Matt Mueller

2 Cevap

Kalıtım tek Tag sınıf içinde farklı etiketler için tüm işlevlerin kapsüllenmesinde daha mantıklı olur. Endişe Ayırma önemli olduğunu, bu nedenle burada bir miras-tabanlı yaklaşım ile gitmek daha iyidir. Aksi takdirde, kötü olan, tek bir sınıf içinde farklı etiket özgü mantığı bir sürü sahip sona. Bu bir bakım kabus!

Eğer Img özgü mantığı varsa, kendi sınıfında koydum. Sen Tag sınıfı içindeki yaygın yöntemlerden tüm koyabilirsiniz. Bu Java olsaydı, ben Tag soyut bir sınıf ya da bir arabirim yapılan ve farklı uygulamalarını (Img, Div, vb) sahip (uzatmak olurdu soyut bir sınıf olması durumunda) ya da) bir arayüz durumunda (uygulanması.

Daha iyi bir yaklaşım, bir Tag arayüze sahip olması, ve sonra tüm ortak mantığı uygulayan bir AbstractTag soyut bir sınıf olacaktır. Sonra özel etiketleri Tag arabirimini uygulayan ve uzatabilirsiniz AbstractTag. Ancak, bu PHP tam olarak mümkün olup olmadığını bilmiyorum, ama benzer bir şey yapmak için deneyebilirsiniz.

Ne new Tag('img'), ne Tag::create('img') bana inandırıcı görünüyor. Bence, kullanmak etiketi yanlış yerde alınır karar - Etiket sınıfta - açıkça Şablon aittir ederken. Etiket ve onun soyundan kullandıkları olacak nasıl hiçbir kontrole sahip olmalıdır.

Ben şu öneririm: Etiketler hiyerarşisini oluşturmak

 abstract class Tag { ...common methods.... }
 class ImgTag extends Tag { ...image specific methods... }
 class SpanTag extends Tag { ...image specific methods... }

İhtiyacınız olduğunda ve Şablon sadece yeni WhateverTag kullanın

 class Template...
    function insertImage
      $tag = new ImgTag($atts);
      $tag->render();

Etiketler birden fazla yerde oluşturulur ise, bir fabrika yöntemini olması iyi bir fikir, ama yine Şablon ait olmalıdır oluyor

 class Template...
    function createImage
      return new ImgTag($atts);

    function insertOneImage
      $tag = $this->createImage
      $tag->render();

    function insertAnotherImage
      $tag = $this->createImage
      $tag->render();

Genel bir tavsiye olarak, herhangi bir fiyata statik yöntemler kaçının. Statik küresel işlevler için sadece fantezi rumuzudur, hiçbir şey nesne yönelimli onlar hakkında.