Статьи

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

Эта статья является частью нашего курса Академии под названием « Шаблоны проектирования Java» .

В этом курсе вы изучите огромное количество шаблонов проектирования и увидите, как они реализуются и используются в Java. Вы поймете причины, почему шаблоны так важны, и узнаете, когда и как применять каждый из них. Проверьте это здесь !

1. Введение

Sec Security System — это охранная и электронная компания, которая производит и собирает товары для автомобилей. Он поставляет любую автомобильную электронную систему или систему безопасности, какую пожелаете, от подушек безопасности до системы GPS-отслеживания, системы парковки задним ходом и т. Д. Крупные автомобильные компании используют эту продукцию в своих автомобилях. Компания использует четко определенный объектно-ориентированный подход для отслеживания своих продуктов с использованием программного обеспечения, которое разработано и поддерживается только ими. Они получают машину, производят для нее систему и собирают ее в машину.

Недавно они получили новые заказы от BigWheel (автомобильная компания) на производство центрального замка и системы блокировки передач для своей новой модели xz. Чтобы поддержать это, они создают новую систему программного обеспечения. Они начали с создания нового абстрактного класса CarProductSecurity, в котором они сохранили некоторые специфичные для автомобиля методы и некоторые функции, которые, по их мнению, являются общими для всех продуктов безопасности. Затем они расширили класс и создали два разных подкласса, названные ими BigWheelXZCentralLocking и BigWheelXZGearLocking. Диаграмма классов выглядит следующим образом:

фигура 1

фигура 1

Через некоторое время другая автомобильная компания Motoren попросила их изготовить новую систему центрального замка и блокировки передач для своей модели lm. Поскольку одна и та же система безопасности не может использоваться в обеих моделях разных автомобилей, Sec Security System создала для них новую систему, а также создала новые классы MotorenLMCentralLocking и MotorenLMGearLocking, которые также расширяют класс CarProductSecurity.

Теперь новая диаграмма классов выглядит следующим образом:

фигура 2

фигура 2

Пока все хорошо, но что произойдет, если другая автомобильная компания потребует еще одну новую систему центрального замка и блокировки передач? Для этого нужно создать еще два новых класса. Этот дизайн создаст один класс на систему или, что еще хуже, если для каждой из этих двух автомобильных компаний будет создана система обратной парковки, для каждой из них будет создано еще два новых класса.

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

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

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

2. Что такое мостовой рисунок

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

Рисунок 3

Рисунок 3

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

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

Уточненная абстракция расширяет интерфейс, определенный абстракцией.

Реализатор предоставляет интерфейс для классов реализации (конкретных реализаторов).

И Конкретный Реализатор реализует интерфейс Реализатора и определяет его конкретную реализацию.

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

3. Решение проблемы

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

Рисунок 4

Рисунок 4

1
2
3
4
5
6
7
package com.javacodegeeks.patterns.bridgepattern;
 
public interface Product {
     
    public String productName();
    public void produce();
}

Product реализатора имеет метод produce() который будет использоваться конкретными исполнителями для предоставления ему конкретной функциональности. Этот метод позволяет получить базовую модель продукта, которую можно использовать с любой моделью автомобиля после некоторых модификаций, характерных для этой модели автомобиля.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.javacodegeeks.patterns.bridgepattern;
 
public class CentralLocking implements Product{
 
    private final String productName;
     
    public CentralLocking(String productName){
        this.productName = productName;
    }
     
    @Override
    public String productName() {
        return productName;
    }
 
    @Override
    public void produce() {
        System.out.println("Producing Central Locking System");
    }
 
}
 
package com.javacodegeeks.patterns.bridgepattern;
 
public class GearLocking implements Product{
 
    private final String productName;
     
    public GearLocking(String productName){
        this.productName = productName;
    }
     
    @Override
    public String productName() {
        return productName;
    }
 
    @Override
    public void produce() {
        System.out.println("Producing Gear Locking System");
    }
 
}

Два разных конкретных реализатора предоставляют реализацию реализатору Product .

Теперь абстракция, класс Car который содержит ссылку на тип продукта и предоставляет два абстрактных метода produceProduct() и produceProduct() assemble() .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package com.javacodegeeks.patterns.bridgepattern;
 
public abstract class Car {
 
    private final Product product;
    private final String carType;
     
    public Car(Product product,String carType){
        this.product = product;
        this.carType = carType;
    }
     
    public abstract void assemble();
    public abstract void produceProduct();
     
    public void printDetails(){
        System.out.println("Car: "+carType+", Product:"+product.productName());
    }
}

Подклассы Car предоставят конкретную и конкретную реализацию методам assemble() и produceProduct() .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.javacodegeeks.patterns.bridgepattern;
 
public class BigWheel extends Car{
 
    private final Product product;
    private final String carType;
     
    public BigWheel(Product product, String carType) {
        super(product, carType);
        this.product = product;
        this.carType = carType;
    }
 
    @Override
    public void assemble() {
        System.out.println("Assembling "+product.productName()+" for "+carType);
    }
 
    @Override
    public void produceProduct() {
        product.produce();
        System.out.println("Modifing product "+product.productName()+" according to "+carType);
    }
 
}
 
package com.javacodegeeks.patterns.bridgepattern;
 
public class Motoren extends Car{
 
    private final Product product;
    private final String carType;
     
    public Motoren(Product product, String carType) {
        super(product, carType);
        this.product = product;
        this.carType = carType;
    }
 
    @Override
    public void assemble() {
        System.out.println("Assembling "+product.productName()+" for "+carType);
    }
 
    @Override
    public void produceProduct() {
        product.produce();
        System.out.println("Modifing product "+product.productName()+" according to "+carType);
    }
 
}

Теперь давайте проверим пример.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.javacodegeeks.patterns.bridgepattern;
 
public class TestBridgePattern {
 
    public static void main(String[] args) {
        Product product = new CentralLocking("Central Locking System");
        Product product2 = new GearLocking("Gear Locking System");
        Car car = new BigWheel(product , "BigWheel xz model");
        car.produceProduct();
        car.assemble();
        car.printDetails();
         
        System.out.println();
         
        car = new BigWheel(product2 , "BigWheel xz model");
        car.produceProduct();
        car.assemble();
        car.printDetails();
         
        System.out.println("-----------------------------------------------------");
         
        car = new Motoren(product, "Motoren lm model");
        car.produceProduct();
        car.assemble();
        car.printDetails();
         
        System.out.println();
         
        car = new Motoren(product2, "Motoren lm model");
        car.produceProduct();
        car.assemble();
        car.printDetails();
         
    }
 
}

Приведенный выше пример выдаст следующий вывод:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
Producing Central Locking System
Modifing product Central Locking System according to BigWheel xz model
Assembling Central Locking System for BigWheel xz model
Car: BigWheel xz model, Product:Central Locking System
 
Producing Gear Locking System
Modifing product Gear Locking System according to BigWheel xz model
Assembling Gear Locking System for BigWheel xz model
Car: BigWheel xz model, Product:Gear Locking System
-----------------------------------------------------
Producing Central Locking System
Modifing product Central Locking System according to Motoren lm model
Assembling Central Locking System for Motoren lm model
Car: Motoren lm model, Product:Central Locking System
 
Producing Gear Locking System
Modifing product Gear Locking System according to Motoren lm model
Assembling Gear Locking System for Motoren lm model
Car: Motoren lm model, Product:Gear Locking System

4. Использование Bridge Pattern

Вы должны использовать шаблон моста, когда:

  1. Вы хотите избежать постоянной связи между абстракцией и ее реализацией. Это может иметь место, например, когда реализация должна быть выбрана или переключена во время выполнения.
  2. И абстракции, и их реализации должны быть расширяемыми подклассами. В этом случае паттерн Bridge позволяет комбинировать различные абстракции и реализации и независимо расширять их.
  3. Изменения в реализации абстракции не должны влиять на клиентов; то есть их код не должен быть перекомпилирован.
  4. Вы хотите разделить реализацию между несколькими объектами (возможно, используя подсчет ссылок), и этот факт должен быть скрыт от клиента.

5. Загрузите исходный код

Это был урок по паттерну моста. Вы можете скачать исходный код здесь: BridgePattern-Project