2016-03-15 1 views
1

Я пытаюсь понять принципы SOLID и поэтому реализовал некоторые фрагменты java. Сейчас моя озабоченность - ОКР. Имея следующие образцы,Применение принципа open/closed в Java

public abstract class Bakery 
{ 
public abstract Bakegood bake(); 
} 

/******************************************/ 

public class BreadBakery extends Bakery { 
@Override 
public Bakegood bake() { 
    return new Bread(); 
} 
} 

/******************************************/ 

public class CakeBakery extends Bakery { 
@Override 
public Bakegood bake() { 
    return new Cake(); 
} 
} 

/******************************************/ 

Как создать правильную пекарню. Предположим, что клиент приходит в пекарню и говорит: «У меня было бы два пирога, пожалуйста!», Как я могу создать экземпляр CakeBakery. Конечно, я могу создать абстрактный завод вроде:

public static Bakery createBakery(final String orderedBakegood) 
{ 
switch(bakegood) 
{ 
    case "Cake": return new CakeBakery(); 
    case "Bread": return new BreadBakery(); 
    default: throw new InvalidBakeryException(); 
} 
} 

Но я не хочу использовать инструкции switch или if. Есть ли другая возможность, или я совершенно не согласен с пониманием?

+1

Что не так с оператором switch или if? Вам нужно как-то принять решение. – Philipp

+0

Коммутатор может работать, но вам нужно открыть его для расширения. Это означает, что вы должны переопределить его, поэтому метод не должен быть статическим. Другое решение - отражение, оно более гибкое. Я хотел бы посмотреть, что другие говорят об этом, я тоже столкнулся с этой проблемой. – Filkolev

+3

@Filkolev Учитывая, что он пытается придерживаться хороших стандартов и узоров, использование отражения здесь будет похоже на то, чтобы стрелять в лицо, потому что вы хотите нарисовать свою стену. – Kayaman

ответ

3

открыто/закрыто принцип гласит:

Программные объекты (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для модификации.

Так что всякий раз, когда вы вводите новую пекарню, вы не должны изменять существующий код. Вы можете использовать что-то вроде реестра для своих классов хлебопекарни. Если вам нужно добавить новую хлебобулочную продукцию, просто добавьте класс хлебопекарни и зарегистрируйте его (например, при запуске). Следовательно, не требуется модификация «if» или «switch». Более того, добавление новой пекарни не требует изменения внутренних компонентов реестра или кода, вызывающего реестр.

Кроме того, эта техника не зависит от способа регистрации ваших компонентов. Вы можете сделать это с программным обеспечением, с конфигурационным файлом (xml, ...), через сканирование по классам, ...

Вы можете увидеть этот подход в Spring Framework много. В принципе, Spring Framework является отличным источником многих принципов дизайна.

Здесь вы можете увидеть очень простую реализацию реестра.

public class BakeryRegistry { 

    private Map<String, Bakery> mapping = new HashMap<>(); 

    public BakeryRegistry() { 
     loadDefaultMappingFromConfigFile(); 
    } 

    public Bakery getBakery(String name) { 
     return mapping.get(name); 
    } 

    public void registerBakery(String name, Bakery bakery) { 
     mapping.put(name, bakery); 
    } 

    private void loadDefaultMappingFromConfigFile() { 
     ... 
    } 
} 

Возможно, статья Killing Switch Statements With A Registry может помочь. Он основан на JavaScript, но принцип тот же.

+0

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

0

Надуманная абстракция вызывает здесь проблему. Клиенты не будут просить пекарню для абстрактных «хлебобулочных изделий», потому что все выпеченные товары не подлежат замене. Хлеб не заменяет торт, и наоборот. Обертка этих двух разных продуктов в одну иерархию наследования является нарушением Принципа замещения Лискова.

Принципы SOLID взаимосвязаны, поэтому применение OCP будет трудным или невозможным без применения LSP в первую очередь. См. introduction to LSP, где Роберт Мартин описывает наследование как критическое для OCP и продолжает описывать LSP как критически важный для наследования.

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