2010-04-24 10 views
2

Извините, мой титул невелик, это мой первый настоящий punt при переходе на 100% в OO, поскольку я был процедурным в течение многих лет, чем я помню. Мне трудно понять, возможно ли то, что я пытаюсь сделать. В зависимости от мысли людей по двум следующим пунктам, я схожу по этому маршруту.Шаблоны для динамических компонентов CMS (событие управляется?)

CMS Я собираю цитату небольшую, однако фокусируется на разных типах контента. Я мог бы легко использовать Drupal, с которым мне очень комфортно, но я хочу дать мне действительно веские причины переместить себя в шаблоны дизайна/OO-PHP

1) Я создал базовый класс контента, который Я хочу иметь возможность распространяться на различные типы контента. Базовый класс, например, обрабатывает содержимое HTML, и расширения могут обрабатывать XML или PDF-вывод. С другой стороны, в какой-то момент я могу полностью расширить базовый класс для данного проекта. То есть если класс 'content-v2' расширенного класса 'content' для этого сайта, любые вызовы этого класса должны фактически называть 'content-v2'. Это возможно?

Если код создает экземпляр объекта типа «content» - я действительно хочу, чтобы он создавал экземпляр одного из типов «content-v2» ... Я могу видеть, как это сделать, используя наследование, но это, как представляется, связано со ссылкой на класс явно, я не вижу, как связать класс, который я хочу использовать, вместо этого динамически.

2) Во-вторых, способ, которым я строил это в настоящий момент, ужасен, я недоволен этим. Он чувствует себя очень линейно, т. Е. Получает информацию о сеансе> получать контент> строить навигацию> тема страницы> публиковать. Для этого все объекты называются 1-на-1, которые все очень статичны. Я бы хотел, чтобы он был более динамичным, чтобы я мог добавить его позже (очень близко к первому вопросу).

Есть ли способ, который вместо моего класса оркестра вызывает все остальные классы 1-на-1, а затем строит все в конце, что вместо этого каждый из других классов может «прослушивать» определенные события, то в подходящую точку прыгать и делать их, но? Таким образом, классу оркестра не нужно было знать, что требовали другие классы, и называть их 1-на-1.

Извините, если у меня все это искривлено в моей голове. Я пытаюсь построить это, чтобы он был очень гибким.

ответ

1

Для вашего вопроса о работе с Content и Content-v2 (которые ужасные имена, кстати) ...

  1. Go подробнее о encapsulation и polymorphism
  2. Я думаю, что вам нужен BaseContent класс, который является абстрактного класса, который никогда не потребляется ни чем иным, как путем наследования.
  3. С вашего BaseContent класса, вы должны иметь HtmlContent, PdfContent, MSWordContent и т. Д. Классы. И если вы хотите, вы можете даже расширять их, например, с помощью HtmlReportContent (extends HtmlContent), MSWord2010Content и т. Д.
  4. Выполнение этого способа позволяет объявлять и сохранять переменные всех типов BaseContent, но при их создании вы создайте их как свой тип. Когда вы это сделаете, даже если у вас есть метод Render(), реализованный в вашем классе BaseContent, ваши дочерние классы могут использовать базовый метод Render() или переопределять его и предоставлять свою собственную реализацию или даже переопределять ее. а затем вызвать базовую реализацию, чтобы воспользоваться этой реализацией.

Если у вас есть общие реализации или поведение (например, Chihuahua и GermanShepard класса будут у обоего есть Bark() функция, но они будут реализованы по-разному), то абстрактно, что общей реализацию или поведение базового класса. Вам необязательно предоставлять реализацию в вашем базовом классе - вот почему это абстрактный класс, а затем заставляет ваши дочерние классы внедрять его (Bark() будет определен в вашем классе BaseDog, но не реализован).

Что касается потока вашей системы ... Для вашего объектно-ориентированного дизайна подумайте о разработке state machine, и ваши объекты по существу заполняют цель конечного автомата и каждое изменение из одного состояния в другое. Да, есть, вероятно, один способ пройти через диаграмму состояния, которая покрывает хорошие 50% сценариев, но мы все знаем, что пользователи будут отклоняться от этого. Таким образом, вам нужно определить способы, с помощью которых пользователь может отклониться от него, и разрешить этим, но ограничивать их. Вы можете или не можете на самом деле вывести схему потока, в зависимости от того, насколько сложна ваша система. Но иногда это помогает визуализировать некоторые возможности, вытягивая часть его. Как правило, хотя эта диаграмма слишком велика для большинства систем OO, которые фактически создаются. Если бы вы делали систему для NASA, вы, вероятно, имели бы ее. :-P

Вот несколько примеров, которые помогут проиллюстрировать некоторые из этих вещей (и рассмотреть некоторые из ваших вопросов в комментариях). Тем не менее, я НЕ являюсь парнем PHP, поэтому я собираюсь дать вам примеры C#, но я буду держать их достаточно простыми, чтобы вы могли легко перевести на PHP.

public interface IAnimal 
{ 
    string GetName(); 
    string Talk(); 
} 

public abstract class AnimalBase : IAnimal 
{ 
    private string _name; 

    // Constructor #1 
    protected AnimalBase(string name) 
    { 
     _name = name; 
    } 

    // Constructor #2 
    protected AnimalBase(string name, bool isCutsey) 
    { 
     if (isCutsey) 
     { 
      // Change "Fluffy" into "Fluffy-poo" 
      _name = name + "-poo"; 
     } 
    } 

    // GetName implemention from IAnimal. 
    // In C#, "virtual" means "Let the child class override this if it wants to but is not required to" 
    public virtual string GetName() 
    { 
     return _name; 
    } 

    // Talk "implementation" from IAnimal. 
    // In C#, "abstract" means "require our child classes to override this and provide the implementation". 
    // Since our base class forces child classes to provide the implementation, this takes care of the IAnimal implementation requirement. 
    abstract public string Talk(); 
} 

public class Dog : AnimalBase 
{ 
    // This constructor simply passes on the name parameter to the base class's constructor. 
    public Dog(string name) 
     : base(name) 
    { 
    } 

    // This constructor passes on both parameters to the base class's constructor. 
    public Dog(string name, bool isCutsey) 
     : base(name, isCutsey) 
    { 
    } 

    // Override the base class's Talk() function here, and this satisfy's AnimalBase's requirement to provide this implementation for IAnimal. 
    public override string Talk() 
    { 
     return "Woof! Woof!"; 
    } 
} 

public class SmallDog : Dog 
{ 
    private bool _isPurseDog; 

    // This constructor is unique from all of the other constructors. 
    // Rather than the second boolean representing the "isCutsey" property, it's entirely different. 
    // It's entirely a coincidence that they're the same datatype - this is not important. 
    // Notice that we're saying ALL SmallDogs are cutsey by passing a hardcoded true into the base class's (Dog) second parameter of the constructor. 
    public SmallDog(string name, bool isPurseDog) 
     : base(name, true) 
    { 
     _isPurseDog = isPurseDog; 
    } 

    // This tells us if the dog fits in a purse. 
    public bool DoesThisDogFitInAPurse() 
    { 
     return _isPurseDog; 
    } 

    // Rather than using Dog's Talk() implementation, we're changing this because this special type of dog is different. 
    public override string Talk() 
    { 
     return "Yip! Yip!"; 
    } 
} 

public class Chihuahua : SmallDog 
{ 
    private int _hatSize; 

    // We say that Chihuahua's always fit in a purse. Nothing else different about them, though. 
    public Chihuahua(string name, int hatSize) 
     : base(name, true) 
    { 
     _hatSize = hatSize; 
    } 

    // Of course all chihuahuas wear Mexican hats, so let's make sure we know its hat size! 
    public int GetHatSize() 
    { 
     return _hatSize; 
    } 
} 

public class Cat : AnimalBase 
{ 
    // This constructor simply passes on the name parameter to the base class's constructor. 
    public Cat(string name) 
     : base(name) 
    { 
    } 

    // This constructor passes on both parameters to the base class's constructor. 
    public Cat(string name, bool isCutsey) 
     : base(name, isCutsey) 
    { 
    } 

    // Override the base class's Talk() function here, and this satisfy's AnimalBase's requirement to provide this implementation for IAnimal. 
    public override string Talk() 
    { 
     return "Meoooowwww..."; 
    } 
} 

public class Lion : Cat 
{ 
    public Lion(string name) 
     : base(name) 
    { 
    } 

    // Rather than using Cat's Talk() implementation, we're changing this because this special type of cat is different. 
    public override string Talk() 
    { 
     return "ROAR!!!!!!!!"; 
    } 
} 

public class ThisIsNotAGoodExampleOfObjectOrientedCoding 
{ 
    public string DoStuff() 
    { 
     // To keep the C#-to-PHP translation easy, think of this as an array of IAnimal objects. 
     List<IAnimal> myAnimals = new List<IAnimal>(); 

     IAnimal strayCat = new Cat("Garfield", false); 
     Cat myPet = new Cat("Katrina"); 
     IAnimal myMothersDog = new Dog("Harley"); 
     Dog myMothersOtherDog = new Dog("Cotton"); 
     IAnimal myNeighborsDog = new SmallDog("Roxy", false); 
     Dog movieStarsDog = new SmallDog("Princess", true); 
     Dog tacoBellDog = new Chihuahua("Larry", 7); 
     Lion lionKing = new Lion("Simba"); 

     myAnimals.Add(strayCat); 
     myAnimals.Add(myPet); 
     myAnimals.Add(myMothersDog); 
     myAnimals.Add(myMothersOtherDog); 
     myAnimals.Add(myNeighborsDog); 
     myAnimals.Add(movieStarsDog); 
     myAnimals.Add(tacoBellDog); 
     myAnimals.Add(lionKing); 

     string allAnimalsTalking = ""; 

     // Create a string to return. 
     // Garfield says "Meow". Fido says "Woof! Woof!" etc... 
     for (int i = 0; i < myAnimals.Count; i++) 
     { 
      allAnimalsTalking = allAnimalsTalking + myAnimals[i].GetName() + " says \"" + myAnimals[i].Talk() + "\" "; 

      if (myAnimals[i] is SmallDog) 
      { 
       // Cast the IAnimal into a SmallDog object. 
       SmallDog yippyDog = myAnimals[i] as SmallDog; 

       if (yippyDog.DoesThisDogFitInAPurse()) 
       { 
        allAnimalsTalking = allAnimalsTalking + " from a purse."; 
       } 
      } 
     } 

     return allAnimalsTalking; 
    } 
} 

Надеюсь, это поможет некоторым.

+0

Хотя он датирован, он выглядит как хороший ресурс (бесплатная PHP OO eBook), чтобы начать работу с некоторыми из основ: http://www.pdf-word.net/Tutorial-Programming-PHP/Object-Oriented-Programming -In-PHP5.html – Jaxidian

+0

Большое спасибо за ваш блестящий ответ, очень ценим! Я думал, что понимаю полиморфизм, но явно не так, как я не верил, что это решение ... Ps эти имена классов не были настоящими, просто попытка проиллюстрировать мой вопрос: 0) – CitrusTree

+0

Так что меня смущает проиллюстрировано здесь: http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming#PHP Я понимаю вещь «Кошка/Собака», но «Кошка и собака» по-прежнему ссылаются на то, чтобы явно их избегать. Как мы называем Cat или Dog в зависимости от текущего состояния. Предположим, что каждая запись в таблице содержимого записала его тип контента. Не могли бы вы использовать что-то вроде: $ content = new $ row ['type']; $ content-> publish; ... где $ row - текущая строка набора записей, а тип - это (допустимое) имя класса? – CitrusTree

Смежные вопросы