Polimorfik / plugable PHP Sınıfları

2 Cevap php

Ben bir tasarım soru sonewhat daha bir sorum var. Ben fonksiyonları bir demet tanımlayan bir sınıf var. Ya da en azından tasarım sırasında bir eklenti arabirimi gibi çalışıyor - Ancak, bazı işlevlerin davranışı çalışma süresinde değiştirilebilir istiyorum. örneğin:

class MyClass {  
  public function doSomething();
}

$obj = new MyClass();
// PSEUDO CODE
$obj->doSomething = doSomethingElse;
$obj->doSomething(); // does something else

Ben "gerçek" kod böyle bir şey uygulamak için nasıl çeşitli fikirler vardı. Ancak, ben gitmek için doğru yolu olan, oldukça emin değilim. Ben ilk bu amaç için bir arabirim kullanabilirsiniz düşündüm.

interface IDoSomethingInterface {  
  public function doSomething();
}

class DoSomethingClass implements IDoSomethingInterface
{
  public function doSomething()
  {
    // I do something!
  }
}

class DoSomethingElseClass implements IDoSomethingInterface
{
  public function doSomething()
  {
    // I actually do something else!
  }
}

class MyClass {
  public doSomething(IDoSomething $doSomethingProvider)
  {
    $doSomethingProvider->doSomething();
  }
}

$obj = new MyClass();
$doSomethingProvider = new DoSomethingClass();
$doSomethingElseProvider = new DoSomethingElseClass();

$obj->doSomething($doSomethingProvider); // I do something!
$obj->doSomething($doSomethingElseProvider); // I do something else!

This approach could be expanded to not have the doSomething provider passed as a parameter, but to set it either as an object member or even class member. However, I did not like that I have to create an instance of n class which does not even contain a single member variable and the only method could easily be a static class function. There's just no need for an object at that point imo. I then was going to try to use function variables - but I'd fall out of OOP then, which I didn't like either. My questions are: which is the best way to implement a system like I described? Which approach would you try or use? Is there anything obvious I might not have thought of? Or should I just go with the interface approach and my bad feeling about instanciating 'bodyless' objects is just nerd preciousness?! I'm curious about your answers!

Edit:

Bu aslında (ya da olmalıdır) bir devlet veya bir Strateji Desen eğer ben açıklama gerçekten ilgileniyorum, çünkü uygulama üzerinde biraz daha detaya gidersiniz. Ben farklı özel uygulamalar türetmek hangi koleksiyonları bir temel sınıf var. Ben herhangi bir uygulama tek bir öğesini seçmek için mümkün olmak istiyorum - Ancak, ben dinamik olarak bu eleman toplama, örneğin seçilir nasıl değiştirmek mümkün istiyorum:

class MyCollection implements Countable, ArrayAcces, Iterator
{
  // Collection Implementation   
  public function select(ISelectionStrategy $strategy)
  {
    return $strategy->select($this);
  }   
} 

interface ISelectionStrategy
{
  public function select(MyCollection $collection);
}  

class AlphaSelectionStrategy implements ISelectionStrategy
{
  public function select(MyCollection $collection);
  {
    reset($collection);
    if (current($collection))
      return current($collection);
    else
      return null;
  }
}

class OmegaSelectionStrategy implements ISelectionStrategy
{
  public function select(MyCollection $collection)
  {
    end($collection);
    if (current($collection))
      return current($collection)
    else
      return null;
  }
}

class RandomSelectionStrategy implements ISelectionStrategy
{
  public function select(MyCollection $collection)
  {
    if (!count($collection))
      return null;
    $rand = rand(0, count($collection)-1);
    reset($collection);
    while($rand-- > 0)
    {
      next($collection);
    }
    return current($collection);
  }
}

$collection = new MyCollection();
$randomStrategy = new RandomSelectionStrategy();
$alphaStrategy = new AlphaSelectionStrategy();
$omegaStrategy = new OmegaSelectionStrategy();

$collection->select($alphaStrategy); // return first element, or null if none
$collection->select($omegaStrategy); // return last element, or null if none
$collection->select($randomStrategy); // return random element, or null if none 

Bu benim ulaşmak istediğim temelde olduğunu. Bu şimdi daha bir strateji desen uygulaması veya devlet desen - zaten bu durumda daha fazla uyuyor çünkü vadeli bir strateji kullanılır olsa. Bildiğim kadarıyla onların niyet dışında strateji ve devlet desen bir temelde aynı, anlamak gibi farklıdır. Ama bu değil durum burada - Gordon tarafından sağlanan bağlantı devlet deseninin niyeti "ne zaman kendi iç durum değişiklikleri bir nesne onun davranışını değiştirmek için izin ver" olduğunu belirtiyor. "Bana kendi devlet yoluyla belirlemek bir algoritma kullanarak bir öğe vermek" değil - Ne istiyorum "Bana bir öğe vermek ya da bu algoritmayı kullanmak" Benim MyCollection sınıf söylemek mümkün olmaktır. Birisi bu netleştirmek Umut!

Best regards, Daniel

2 Cevap

Sizin yaklaşım doğru değildir. Bu bir Strategy Pattern (UML diagram):

Bu soruya cevabım Çıkış (diyor nerede atlamak Since you want to dynamically change behavior):

Özel usecase alternatif bir yerine Koleksiyon bunları sınıfa atama, bir tek Servis sınıfa Seçim Stratejileri Kapsüle olacaktır. Sonra yerine toplama stratejileri geçme, örneğin, Hizmet Sınıfı için koleksiyon geçmek

class CollectionService implements ICollectionSelectionService
{
    public static function select(MyCollection $collection, $strategy) {
        if(class_exists($strategy)) {
            $strategy = new $strategy;
            return $strategy->select($collection);
        } else { 
            throw new InvalidArgumentException("Strategy does not exist");
        }    
    }
}
$element = CollectionService::select($myCollection, 'Alpha');

Ben statik yöntemler ya da değil, bu kullanmak isteyip size bırakıyorum. Seçim stratejileri birden Destekleme önlemek için, yeniden kullanım için Servis'ten Seçim nesneleri depolamak olabilir.

Diğer Davranış Kalıpları kontrol için

Eğer özetlenen çözümü daha fazla ya da daha az doğru. Bunu bilmiyor olabilir, ama bu aslında "State" Design Pattern olduğunu. Sistemin State nesne ile temsil edilmektedir. Eğer durumunu değiştirmek gerekiyorsa, sadece başka bir Devlet ile nesneyi değiştirin.

alt text

Bu çözüm olduğu GOF tarafından kanıtlanmış gibi, ne var ile kalıyorum tavsiye ederim.