Шаблон метода шаблона и шаблон построителя шаблонов проектирования Java

Java задняя часть алгоритм Шаблоны проектирования

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)

"ReentrantLock из Java Lock (2)

"ReentrantReadWriteLock блокировки Java