2016-07-10 2 views
0

Я узнаю о составном шаблоне дизайна, и я не понимаю, как я могу обрабатывать каждый компонент одинаково (Лист и композит), когда каждый раз, когда я пытаюсь добавить или удалить компонент из листа Я должен получить ошибку (или ничего не должно произойти). Кажется, это ужасный дизайн для меня, потому что он нарушает правило наследования, чтобы лечить объекты одинаково. Единственный способ - это каким-то образом отличить Композит от Листа и всегда знать, с чем я работаю. Но это возвращает меня к исходной задаче ...Правильный способ использования композитного рисунка

Компонент:

public abstract class Equipment { 
    private String name; 

    protected Equipment(String name){ 
     this.name = name; 
    } 

    public String name(){ 
     return name; 
    } 


    public abstract int power(); 
    public abstract double netPrice(); 
    public abstract double discountPrice(); 

    public abstract void add(Equipment equipment); 
    public abstract void remove(Equipment equipment); 

    public Iterable<Equipment> createIterator(){ 
     return Collections.emptyList(); 
    } 
} 

Композитный:

public abstract class CompositeEquipment extends Equipment{ 
    private final List<Equipment> elements; 

    protected CompositeEquipment(String name) { 
     super(name); 
     elements = new LinkedList<>(); 
    } 

    @Override 
    public double netPrice() { 
     Iterable<Equipment> iter = createIterator(); 
     double total = 0; 

     for (Iterator<Equipment> i = iter.iterator(); i.hasNext() ;) { 
      Equipment next = i.next(); 
      total += next.netPrice(); 
     } 

     return total; 
    } 

    @Override 
    public Iterable<Equipment> createIterator() { 
     return elements; 
    } 

    @Override 
    public void remove(Equipment equipment){ 
     elements.remove(equipment); 
    } 

    @Override 
    public void add(Equipment equipment){ 
     elements.add(equipment); 
    } 

} 

Лист:

public class FloppyDisk extends Equipment{ 

    public FloppyDisk(String name) { 
     super(name); 
    } 

    @Override 
    public int power() { 
     return 1; 
    } 

    @Override 
    public double netPrice() { 
     return 3; 
    } 

    @Override 
    public double discountPrice() { 
     return 2.2; 
    } 

    @Override 
    public void add(Equipment equipment) { 
     //we well do nothing here because thats the final element of the tree 
    } 

    @Override 
    public void remove(Equipment equipment) { 
     //we well do nothing here because thats the final element of the tree 
    } 

} 

Проблемы я вижу:

public void extendTheTree(Equipment equipment){ 
    equipment.add(new CompositeWithLeafs()); //lets hope it is a Composite not a Leaf!!! 
} 

Так как я должен использовать этот шаблон, то или в каком-то сценарии ??? Единственное решение, которое я вижу, это избавиться от концепции Leaf и использовать только Composits.

ответ

2

Корень вашего недоразумения заключается в том, что вы использовали методы, которые имеют смысл для Leaf, и методы, которые имеют смысл для Composite и объединяют эти методы в public abstract class Equipment, то есть ваш компонент. Таким образом, у вас появился общий предок для Leaf и Composite, частью которого предок не имеет смысла для Leaf. Я говорю о методах add и remove, которые не имеют смысла для Листа и поэтому не должны быть частью Компонента в первую очередь. Если вы хотите использовать абстрактный класс или интерфейс для представления своего компонента, это еще одна проблема, и вы можете найти идеальный анализ на этом сайте. Но факт заключается в том, что Компонент должен содержать пересечение методов Листа и методов Composite, набор методов, которые могут использоваться на объекте, не зная, является ли он Листом или композитом. Более формально Компонент должен определить общий интерфейс, который должен быть реализован Листом и композитом. Если вы пойдете на это так, вы обнаружите, что никогда не сможете найти add Лист, потому что интерфейс Component не должен иметь такой метод, чтобы переопределить, и Leaf не должен иметь такого метода. К лучшему или худшему, вы можете только add что-то, что вы знаете, это композит.

+0

Вы хотите переместить методы 'add' и' remove' в класс 'CompositeEquipment'? – Tomasz

+0

@Tomek Да, 'add' и' remove' не должны быть в компоненте, они не должны быть частью интерфейса Component. Они должны быть определены только в Composite. После того, как вы это сделаете, вы обнаружите, что некоторые дизайнерские решения приходят естественным образом. – xnakos

+0

, но затем вы теряете прозрачность, потому что у листьев и композитов теперь есть разные интерфейсы. Это не то, о чем эта картина. Наверное, я пытаюсь съесть пирог и пирог. – Tomasz

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