1. Предварительный обзор
Предыдущий«Шаблон фабричного метода и абстрактный фабричный шаблон шаблонов проектирования Java»Представлены три фабричных шаблона, а именно шаблон фабричного метода, простой шаблон фабричного метода и абстрактный шаблон фабрики.В статье подробно представлены определение и практика трех шаблонов в соответствии с реальной сценой, и, наконец, резюмируется разница между тремя шаблонами и различия каждого шаблона Применимая сцена. В этом сообщении блога давайте изучим шаблон метода шаблона и шаблон построителя.
2. Определение и применение шаблона метода шаблона и шаблона построителя
2.1 Определение и применение шаблона шаблонного метода
Определение: Определяет скелет алгоритма в операции, откладывая некоторые шаги на подклассы Шаблонный метод позволяет подклассам переопределять определенные шаги алгоритма без изменения структуры алгоритма.
Перевод: определить структуру алгоритма в операции, тем самым отложив некоторые шаги в подклассе. Это позволяет подклассам переопределять определенные шаги алгоритма без изменения структуры алгоритма.
На самом деле, в соответствии с приведенным выше определением, мы можем быстро подумать, что определение этого шаблона не является наследованием? Да, именно так, самая простая реализация паттерна шаблонного метода — это наследование. Давайте сначала реализуем шаблон метода шаблона с кодом. Я считаю, что все ели лапшу быстрого приготовления, давайте использовать режим метода шаблона, чтобы сделать лапшу.
public abstract class AbstractTemplate {
/**
* 烧开水*/
public abstract void boilWater();
/**煮面条*/
public abstract void cookNoodles();
/**放调料*/
public abstract void putCondiment();
/**定义煮面的模板,先烧水,再放面条,最后放调料*/
public void finish(){
boilWater();
cookNoodles();
putCondiment();
System.out.println("煮完啦,开吃咯!");
}
}
/**煮方便面模板实现类*/
public class InstantNoodlesTemplate extends AbstractTemplate{
@Override
public void boilWater() {
System.out.println("烧开水啦!");
}
@Override
public void cookNoodles() {
System.out.println("放入方便面啦!");
}
@Override
public void putCondiment() {
System.out.println("可以放调料啦!");
}
}
/**客户端场景类*/
public class Client {
public static void main(String[] args) {
AbstractTemplate template=new InstantNoodlesTemplate();
template.finish();
}
}
вышеfinish()
Метод заключается в определении структуры алгоритма, которая определяет этапы алгоритма сначала кипячения воды, затем добавления лапши и, наконец, приправы. Затем каждый подкласс реализует конкретную реализацию того, как кипятить воду, какую лапшу класть и какие приправы класть. Это шаблон метода шаблона, реализованный просто через наследование. Это так просто, давайте взглянем на другой паттерн, знакомый с паттерном метода шаблона, — паттерн построителя.
2.21 Определение и применение шаблона Builder
Определение: Отделите построение сложного объекта от его представления, чтобы один и тот же процесс построения мог создавать разные представления.
Перевод: отделение построения сложного объекта от его представления, чтобы один и тот же процесс построения мог создавать разные представления.
сосредоточься здесь,Разделение построения и представления сложных объектов, который используется здесь в приведенной выше сцене приготовления, означает, что алгоритм и определение приготовления лапши являются отдельными, то есть конкретные шаги алгоритма, такие как, как приготовить лапшу, как положить приправы и т. д., определяются каждым конкретным типом лапши. Давайте реализуем это в коде:
//抽象煮苗条类
public abstract class AbstractNoodlesMode {
private List<String> stepOrders = new ArrayList<>();
/**
* 烧开水
*/
public abstract void boilWater();
/**
* 煮面条
*/
public abstract void cookNoodles();
/**
* 放调料
*/
public abstract void putCondiment();
/**
* 煮面条其他步骤
*/
public abstract void doOther();
/**
* 根据传入的工序进行加工煮面
*/
final public void finish() {
for (String stepOrder : this.stepOrders) {
switch (stepOrder) {
case "boilWater":
boilWater();
break;
case "cookNoodles":
cookNoodles();
break;
case "putCondiment":
putCondiment();
break;
case "doOther":
doOther();
break;
default:
System.out.println("无法识别的烹饪指令");
break;
}
}
}
final public void setStepOrders(List<String> stepOrders) {
this.stepOrders = stepOrders;
}
}
/**方便面的实现类,由于只需要烧水,煮面,放调料就行了,other方法就为空*/
public class InstantNoodles extends AbstractNoodlesMode {
@Override
public void boilWater() {
System.out.println("煮开水");
}
@Override
public void cookNoodles() {
System.out.println("放入方便面");
}
@Override
public void putCondiment() {
System.out.println("放入调料");
}
@Override
public void doOther() {
}
}
/**意大利面条实现类*/
public class Spaghetti extends AbstractNoodlesMode {
@Override
public void boilWater() {
System.out.println("煮开水");
}
@Override
public void cookNoodles() {
System.out.println("放入意大利面");
}
@Override
public void putCondiment() {
System.out.println("放入番茄酱");
}
@Override
public void doOther() {
System.out.println("放入火腿,早餐肉");
}
}
/**抽象建造者类*/
public abstract class AbstractBuilder {
/**定义煮面条工序*/
public abstract AbstractBuilder cookNoodles();
/**完成面条*/
public abstract AbstractNoodlesMode build();
}
/**泡面建造者实现类*/
public class InstantNoodlesBuilder extends AbstractBuilder {
private AbstractNoodlesMode noodles=new InstantNoodles();
@Override
public AbstractBuilder cookNoodles() {
List<String> steps=new ArrayList<>();
//烧水
steps.add("boilWater");
//放面条
steps.add("cookNoodles");
//放调料
steps.add("putCondiment");
this.noodles.setStepOrders(steps);
return this;
}
@Override
public AbstractNoodlesMode build() {
return this.noodles;
}
}
/*意大利面条建造者实现类**/
public class SpaghettiBuilder extends AbstractBuilder {
private AbstractNoodlesMode noodle = new Spaghetti();
@Override
public AbstractBuilder cookNoodles() {
List<String> steps = new ArrayList<>();
//烧水
steps.add("boilWater");
//放面条
steps.add("cookNoodles");
//放调料
steps.add("putCondiment");
//放火腿,放早餐肉
steps.add("doOther");
this.noodle.setStepOrders(steps);
return this;
}
@Override
public AbstractNoodlesMode build() {
return this.noodle;
}
}
/**客户端场景类*/
public class Client {
public static void main(String[] args) {
AbstractBuilder instantNoodleBuilder = new InstantNoodlesBuilder();
AbstractBuilder spaghettiBuilder = new SpaghettiBuilder();
AbstractNoodlesMode instantNoodle = instantNoodleBuilder.cookNoodles().build();
instantNoodle.finish();
System.out.println("--------------------");
AbstractNoodlesMode spaghe = spaghettiBuilder.cookNoodles().build();
spaghe.finish();
}
}
Мы запускаем результат следующим образом:
Мы организуем приведенный выше код в диаграмму классов следующим образом:
В приведенной выше диаграмме классов я опустил класс реализации noodle, но это не влияет на понимание всего шаблона билдера. Некоторые студенты обязательно спросят, хотя этот режим конструктора немного сложнее, чем режим метода шаблона, но я чувствую, что они очень похожи, немного запутанны. Да, верно, они знают друг друга. Но мы можем хорошо различить их, просто вспомнив одну вещь.
- Шаблон метода шаблона определил алгоритм компоновщика, то есть процесс, что делать сначала, а что потом.
- Шаблон построителя не определяет процесс построителя, а предоставляет подклассам возможность реализовать алгоритм построителя, то есть сам процесс.
Пока мы помним об этом, мы можем хорошо отличать шаблон метода шаблона от шаблона построителя, а также знать, когда использовать шаблон метода шаблона и когда использовать шаблон построителя.
3. Сценарии применения шаблона метода шаблона и шаблона построителя
3.1 Сценарии использования паттерна шаблонного метода
1. Когда несколько подклассов имеют общедоступные методы и логика в основном одинакова.
2. Когда требуется сложный алгоритм с важными ядрами и требуется много повторного использования, алгоритм может быть реализован в режиме шаблонного метода.
3. При рефакторинге и обновлении кода режим метода шаблона является очень распространенным режимом.Как правило, для обеспечения обратной совместимости используется режим метода шаблона, и в методе шаблона устанавливаются функции-ловушки для выполнения различных функций в соответствии с различными версии и разные ситуации алгоритм.
3.2 Сценарии использования режима строителя
1. Режим построителя можно использовать, когда генерируется один и тот же метод, разный порядок выполнения и разные результаты событий.
2. Несколько компонентов или частей могут быть собраны в объект, но результаты будут разными.
В-четвертых, преимущества и недостатки шаблона метода шаблона и шаблона построителя.
4.1 Шаблон метода шаблона
преимущество:
- Хорошая расширяемость, подклассам нужно только реализовать заданный алгоритм, и не нужно обращать внимание на алгоритм последующего объединения
- Хорошая ремонтопригодность.
- Соблюдайте принцип инверсии зависимостей
недостаток:
- Недостатком в личном понимании может быть то, что основной метод комбинирования инкапсулирован, но это характеристика шаблонного метода, так что будем считать это недостатком.
4.2 Режим строителя
преимущество:
- Он так же расширяем и удобен в сопровождении, как шаблон метода шаблона.
- Гибкость, потому что даже самый основной алгоритм комбинации передается для реализации подклассам, поэтому он более гибкий.
недостаток:
- Риск, потому что алгоритм комбинации освобождается, ограничение уменьшается. Следовательно, это может привести к тому, что подкласс вызовет неправильный алгоритм, что создаст потенциальные риски для системы.
V. Резюме
Шаблон метода шаблона и шаблон построителя являются креативными шаблонами. Коды двух шаблонов очень похожи, и их легко спутать. Нам нужно только помнить их основные различия, чтобы знать, когда использовать шаблон метода шаблона и когда использовать шаблон метода. выкройка построителя модель. Здесь снова их основные отличия:Шаблон метода шаблона определяет основной алгоритм, то есть процесс сборки, в то время как шаблон строителя не определяет порядок построения и количество конструируемых частей.Окончательный основной процесс и использование частей полностью определяются подклассами.
Подробные и внимательные читатели наверняка заметили, что реализация в моем шаблоне сборки появиласьinstantNoodleBuilder.cookNoodles().build()
такA.B.C
Кодекс, мы говорили о законе Деметры ранее в начале нашего шаблона проектирования, закон Деметры имеет пример, который говорит не появлятьсяA.B.C
В данном случае здесь поясняется, что требование Закона Деметры состоит в том, чтобы не полагаться на не-друзей, а на самом деле не появлятьсяA.getB.getC
, а тут ведь каждый раз возвращаетсяthis
, так что все они зависят от самих себя, и нет недружественного класса, так что такой способ записи не нарушает Закон Деметры.
6. Ссылка
Дзен шаблонов проектирования
7. Рекомендуемое чтение
"Шаблон фабричного метода и абстрактный фабричный шаблон шаблонов проектирования Java》
"Шаблон Singleton в шаблонах проектирования Java》
"Начало шаблонов проектирования JAVA》
"Перенесет вас в ArrayList коллекций Java》
"Перенесем вас в HashMap коллекции java》
"ReentrantLock блокировки Java (1)》