2013-04-15 3 views
2

У меня есть вопрос относительно шаблонов дизайна.дизайн шаблон запрос

Предположим, я хочу создать свинью убийство фабрики

поэтому пути будут

1) поймать свинью

2) чистая свинья

3) убить свинью

прямо сейчас поскольку эти свиньи поставляются мне водителем грузовика

теперь, если хотят создать приложение, как я должен продолжить то, что я сделал это

public class killer{ 
private Pig pig ; 
public void catchPig(){ //do something }; 
public void cleanPig(){ }; 
public void killPig(){}; 
} 

Теперь РМКА вещь, так как я знаю, что шаги будут называться в catchPig--->cleanPig---->KillPig образом, поэтому я должен иметь абстрактный класс, содержащий эти методы и метод execute, вызывающий все эти 3 метода.

но я не могу иметь экземпляр абстрактного класса, поэтому я смущен, как реализовать это. remenber Я должен выполнить этот процесс для всех свиней, которые входят в грузовик.

так что мой вопрос в том, какой дизайн я должен выбрать, и какой шаблон дизайна лучше всего решать такие проблемы.

+0

почему отрицательный голос :( –

+1

Я думаю, что это вегетарианское – devdigital

+0

Вы только собираетесь убить свиней или других животных, а также приветствовать? – Bart

ответ

3

Я бы предложил другой подход, чем предлагалось здесь раньше.

Я хотел бы сделать что-то вроде этого:

public abstract class Killer { 
    protected Pig pig; 

    protected abstract void catchPig(); 

    protected abstract void cleanPig(); 

    protected abstract void killPig(); 

    public void executeKillPig { 
     catchPig(); 
     cleanPig(); 
     killPig(); 
    } 
} 

Каждое убийство продлит Killer класса и должны реализовать абстрактные методы. executeKillPig() одинаково для каждого подкласса и всегда будет выполняться в том порядке, в котором вы хотите catch-> clean-> kill. Абстрактные методы защищены, потому что они являются внутренней реализацией общественности executeKillPig.

+1

+1. Лучше, чем интерфейс. Здесь шаги всегда будут выполняться в правильном порядке. Интерфейс не может этого гарантировать. (P.S. это называется шаблоном шаблона). Кроме того, важно подчеркнуть намерение: каждый подкласс IS A 'Killer' vis-a-vis с интерфейсом, который мы разрешаем любому произвольному классу Killer _behavior_. Но с точки зрения доменной точки зрения это не имеет смысла. Мы хотим сказать/подчеркнуть/укрепить код, что каждый объект, который делает это, является «Убийцей», и, конечно же, не «вегетарианцем». – radarbob

+0

Кулак всего, что вы не можете гарантировать, что он имеет только абстрактный класс. Вы можете только советовать/предлагать, но когда у вас есть абстрактный класс, каждый общедоступный/защищенный метод может быть изменен. Шаблон шаблона увеличивает привязку к предмету, поэтому он не лучший вариант. ИМХО следует избегать. Маршрут, который реализован в шаблоне, может быть в какой-то момент изменен, тогда нам нужно беспокоиться обо всех классах, которые его реализуют. Более гибким способом является наличие другого объекта, который захватывает объект-убийца и манипулирует им по мере необходимости. –

+1

@Vash, я согласен, что «не может заверить, что иметь ... абстрактный класс». Да, вы можете вызвать подклассу 'Killer'' Vegetarian', если хотите, и переопределить методы, но мой аргумент не связан с механикой кодирования. Я думаю, вы получаете аргумент семантики: в этом ответе явно говорится о «свиньях», а не о «животных» вообще. Тем не менее, если класс 'Killer' обрабатывал' Animal' вместо 'Pig', то я все же использовал бы абстрактный базовый класс с шаблоном шаблона, а не с интерфейсом. – radarbob

0

Проблемы вы столкнулись относитесь к части ООП называется polymorphism

Вместо абстрактного класса я буду использовать интерфейс, разница между интерфейсом абстрактным классом является то, что интерфейс есть только описание методов, абстрактная класс может также имеют метод реализации.

public interface InterfaceOfPigKiller { 

    void catchPig(); 
    void cleanPig(); 
    void killPig(); 
} 

В абстрактном классе мы реализуем два из трех доступных методов, потому что мы считаем, что те операции являются общими для каждого будущего типа, которые унаследуют формируют наш класс.

public abstract class AbstractPigKiller implements InterfaceOfPigKiller{ 

    private Ping pig; 

    public void catchPig() { 
    //the logic of catching pigs. 
    } 

    public void cleanPig() { 
    // the logic of pig cleaning. 
    } 

} 

Теперь мы создадим два новых класса:

  • AnimalKiller - Лицо, ответственное за смерть свиней.

  • AnimalSaver - лицо, ответственное за выпуск свиней.


public class AnimalKiller extends AbstractPigKiller { 

public void killPig() { 
    // The killing operation 
} 

} 

public class AnimalSaver extends AbstractPigKiller { 

public void killPing() { 
    // The operation that will make pig free 
} 

} 

Как у нас есть структура позволяет увидеть, как он будет работать.

Первый метод, который будет выполнять последовательность:

public void doTheRequiredOperation(InterfaceOfPigKiller killer) { 

    killer.catchPig(); 
    killer.cleanPig(); 
    killer.killPig(); 
} 

Как мы видим, в параметре мы не используем класс AnimalKiller или AnimalSever. Вместо этого у нас есть интерфейс.Благодаря этой операции мы можем работать с любым классом, реализующим используемый интерфейс.


Пример 1:

public void test() { 

    AnimalKiller aKiller = new AnimalKiller();// We create new instance of class AnimalKiller and assign to variable aKiller with is type of `AnimalKilleraKiller ` 
    AnimalSaver aSaver = new AnimalSaver(); // 

    doTheRequiredOperation(aKiller); 
    doTheRequiredOperation(aSaver); 


} 

Пример 2:

public void test() { 

    InterfaceOfPigKiller aKiller = new AnimalKiller();// We create new instance of class AnimalKiller and assign to variable aKiller with is type of `InterfaceOfPigKiller ` 
    InterfaceOfPigKiller aSaver = new AnimalSaver(); // 

    doTheRequiredOperation(aKiller); 
    doTheRequiredOperation(aSaver); 


} 

Код примера 1 и 2 одинаково в рамках метода doTheRequiredOperation. Разница в том, что мы присваиваем тип type type, а во втором мы присваиваем тип интерфейсу.

Заключение

Мы не можем создать новый объект абстрактного класса или интерфейса, но мы можем назначить объект для интерфейса или типа класса.

+0

-1. Это хороший пример злоупотребления интерфейсами IMHO; и это путаный полиморфизм и наследование концептуально.Здесь абсолютно никакой необходимости в том, чтобы «абстрактный» класс реализовал интерфейс. Сам класс может объявлять и определять необходимые методы. Концептуально интерфейс наполняет (ограниченным/конкретным) _behavior_, давая любому объекту эту способность, пока он _IS_ что-то еще. OTOH подкласс 'PigKiller' является рожденным' Killer' и _inherently_ имеет все поведение 'Killer'. – radarbob

+0

Интерфейс был введен, чтобы продемонстрировать концепцию, поскольку использование абстрактного класса и класса иногда является сложным. Отображение того, что абстрактный класс является чем-то вроде интерфейса, но мы можем иметь общую реализацию, это проще. Поскольку представленный пример далек от правильности. Ваше мнение ошибочно. Тебе нужно, чтобы абстрактный класс рядом с приведенным выше объяснением делился общим действием, таким как «catchPig» и «cleanPig», мы оставили открытым для ребенка, как бы хотелось иметь дело с свинью. Представляя интерфейс, мы даем изменения, чтобы иметь совершенно другое убийство. –

+0

@radarbob, Это предотвратит нечто вроде расширенного абстрактного и переопределит два из трех методов. Поэтому абстрактных классов следует избегать, не поощряя ИМХО. Я бы не использовал абстрактный класс здесь, но вопрос требовал этого. –

1

Это расширяет ответ Ави и рассматривает комментарии.

Точка коды:

  1. abstract базового класс, чтобы подчеркнуть являются отношениями
  2. шаблон шаблона для обеспечения шагов в правильном порядке
  3. Стратегии Pattern - abstract класса как много интерфейс (маленький «i») до Interface (столица «I»).
  4. Расширьте базу и не используйте интерфейс.
  5. Отсутствие сцепления классов бетона. Сцепление не является вопросом abstract vs interface, но неплохой дизайн.
 
    public abstract Animal { 
     public abstract bool Escape(){} 
     public abstract string SaySomething(){} 
    } 

    public Wabbit : Animal { 
     public override bool Escape() {//wabbit hopping frantically } 
     public override string SaySomething() { return @"What's Up Doc?"; } 
    } 


    public abstract class Killer { 
     protected Animal food; 
     protected abstract void Catch(){} 
     protected abstract void Kill(){} 
     protected abstract void Clean(){} 

     protected abstract string Lure(){} 

     // this method defines the process: the methods and the order of 
     // those calls. Exactly how to do each individual step is left up to sub classes. 
     // Even if you define a "PigKiller" interface we need this method 
     // ** in the base class ** to make sure all Killer's do it right. 
     // This method is the template (pattern) for subclasses. 
     protected void FeedTheFamily(Animal somethingTasty) { 
      food = somethingTasty; 
      Catch(); 
      Kill(); 
      Clean(); 
     } 

    } 
    public class WabbitHunter : Killer { 
     protected override Catch() { //wabbit catching technique } 
     protected override Kill() { //wabbit killing technique } 
     protected override Clean() { //wabbit cleaning technique } 
     protected override Lure() { return "Come here you wascuhwy wabbit!"; } 

    } 

    // client code ******************** 
    public class AHuntingWeWillGo { 
     Killer hunter; 
     Animal prey; 

     public AHuntingWeWillGo (Killer aHunter, Animal aAnimal) { 
      hunter = aHunter; 
      prey = aAnimal; 
     } 

     public void Hunt() { 
      if (!prey.Escape()) hunter.FeedTheFamily(prey) 
     } 
    } 


    public static void main() { 
     // look, ma! no coupling. Because we pass in our objects vice 
     // new them up inside the using classes 

     Killer ElmerFudd = new WabbitHunter(); 
     Animal BugsBunny = new Wabbit(); 
     AHuntingWeWillGo safari = new AHuntingWeWillGo(ElmerFudd, BugsBunny); 

     safari.Hunt(); 
    } 

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