Основной целью шаблонов проектирования прототипов является клонирование уже существующего объекта, когда создание нового объекта очень дорого. Просто означает, что дизайн прототипа позволит избежать создания нового объекта. В таких ситуациях, как создание тысяч объектов каждый раз, тогда как создание приложения для объекта очень дорого, шаблон проектирования прототипа является наиболее подходящим шаблоном проектирования.
Для реализации шаблона проектирования прототипа в Java требуется клонируемый класс интерфейса.
Примечание. Класс клонируемого интерфейса всегда возвращает тип объекта, а не общий, поскольку разработчику необходимо преобразовать каждый объект, клонированный с помощью клонируемого интерфейса.
Важно: при клонировании объектов разработчику необходимо учитывать, какой тип клонирования подходит для данной архитектуры. Есть два типа клонирования,
1. Поверхностное копирование
2. Глубокое копирование
Поверхностное копирование. Скопируйте объект первого уровня и ссылки на новый объект.
Примечание. Это может привести к другой серьезной проблеме, если элементы значений будут изменены с помощью какой-либо другой ссылки.
Глубокое копирование: при глубоком копировании он не только клонирует объект первого уровня, но также копирует каждое значение и ссылки на новый объект.
Пример. Предположим, что авиакомпании требуется программное обеспечение для обработки авиабилетов, и доступны три типа билетов.
Шаг 1:
Создайте абстрактный класс с именем AirlineTicket.
package PrototypeExample; public abstract class AirlineTicket implements Cloneable { private String flightNumber; private double duration; private String departure; private String arrival; private String seatNumber; public String getFlightNumber() { return flightNumber; } public void setFlightNumber(String flightNumber) { this.flightNumber = flightNumber; } public double getDuration() { return duration; } public void setDuration(double duration) { this.duration = duration; } public String getDeparture() { return departure; } public void setDeparture(String departure) { this.departure = departure; } public String getArrival() { return arrival; } public void setArrival(String arrival) { this.arrival = arrival; } public String getSeatNumber() { return seatNumber; } public void setSeatNumber(String seatNumber) { this.seatNumber = seatNumber; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
Реализуйте клонируемый интерфейс для клонирования экземпляров. А также реализовать сеттеры и геттеры.
Шаг 2:
Создайте дочерние классы класса AirlineTicket.
Эконом-класс:
package PrototypeExample; public class EconomyClass extends AirlineTicket{ private boolean needAssistant; public boolean isNeedAssistant() { return needAssistant; } public void setNeedAssistant(boolean needAssistant) { this.needAssistant = needAssistant; } @Override public String toString() { return "EconomyClass{" + "flightNumber='" + super.getFlightNumber() + '\'' + ", duration=" + super.getDuration() + ", departure='" + super.getDeparture() + '\'' + ", arrival='" + super.getArrival() + '\'' + ", seatNumber='" + super.getSeatNumber() + '\'' + "needAssistant=" + needAssistant + '}'; } }
Бизнес-класс:
package PrototypeExample; public class BusinessClass extends AirlineTicket{ private boolean needOnBoardDrink; private boolean loungeAccess; private boolean VIPTransport; public boolean isNeedOnBoardDrink() { return needOnBoardDrink; } public void setNeedOnBoardDrink(boolean needOnBoardDrink) { this.needOnBoardDrink = needOnBoardDrink; } public boolean isLoungeAccess() { return loungeAccess; } public void setLoungeAccess(boolean loungeAccess) { this.loungeAccess = loungeAccess; } public boolean isVIPTransport() { return VIPTransport; } public void setVIPTransport(boolean VIPTransport) { this.VIPTransport = VIPTransport; } @Override public String toString() { return "BusinessClass{" + "flightNumber='" + super.getFlightNumber() + '\'' + ", duration=" + super.getDuration() + ", departure='" + super.getDeparture() + '\'' + ", arrival='" + super.getArrival() + '\'' + ", seatNumber='" + super.getSeatNumber() + '\'' + ", needOnBoardDrink=" + needOnBoardDrink + ", loungeAccess=" + loungeAccess + ", VIPTransport=" + VIPTransport + '}'; } }
Первый класс:
package PrototypeExample; public class FirstClass extends AirlineTicket{ private boolean needOnBoardDrink; private boolean loungeAccess; public boolean isNeedOnBoardDrink() { return needOnBoardDrink; } public void setNeedOnBoardDrink(boolean needOnBoardDrink) { this.needOnBoardDrink = needOnBoardDrink; } public boolean isLoungeAccess() { return loungeAccess; } public void setLoungeAccess(boolean loungeAccess) { this.loungeAccess = loungeAccess; } @Override public String toString() { return "FirstClass{" + "flightNumber='" + super.getFlightNumber() + '\'' + ", duration=" + super.getDuration() + ", departure='" + super.getDeparture() + '\'' + ", arrival='" + super.getArrival() + '\'' + ", seatNumber='" + super.getSeatNumber() + '\'' + ", needOnBoardDrink=" + needOnBoardDrink + ", loungeAccess=" + loungeAccess + '}'; } }
Создайте геттеры и сеттеры для каждого класса.
Шаг 3.
Создайте класс enum для представления типов авиабилетов.
package PrototypeExample; public enum AirlineTicketType { ECONOMY, BUSINESS, FIRST }
Шаг 4:
Создайте класс реестра.
Этот класс отвечает за первоначальное создание объекта.
Примечание. Разработчику необходимо использовать «новые» ключевые слова только при первоначальном создании экземпляра.
package PrototypeExample; import java.util.HashMap; import java.util.Map; public class Registry { private Map<AirlineTicketType, AirlineTicket> tickets = new HashMap<>(); public Registry() { this.initialize(); } public AirlineTicket getTicket (AirlineTicketType airlineTicketType) { AirlineTicket airlineTicket = null; try { airlineTicket = (AirlineTicket) tickets.get(airlineTicketType).clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return airlineTicket; } private void initialize() { EconomyClass economyClass = new EconomyClass(); economyClass.setFlightNumber("AB1"); economyClass.setDuration(4.5); economyClass.setDeparture("CMB"); economyClass.setArrival("KUL"); economyClass.setSeatNumber("AA12"); BusinessClass businessClass = new BusinessClass(); businessClass.setFlightNumber("AB1"); businessClass.setDuration(4.5); businessClass.setDeparture("CMB"); businessClass.setArrival("KUL"); businessClass.setSeatNumber("BB21"); businessClass.setNeedOnBoardDrink(true); businessClass.setLoungeAccess(true); businessClass.setVIPTransport(true); FirstClass firstClass = new FirstClass(); firstClass.setFlightNumber("AB1"); firstClass.setDuration(4.5); firstClass.setDeparture("CMB"); firstClass.setArrival("KUL"); firstClass.setSeatNumber("CC34"); firstClass.setNeedOnBoardDrink(true); firstClass.setLoungeAccess(true); tickets.put(AirlineTicketType.ECONOMY, economyClass); tickets.put(AirlineTicketType.BUSINESS, businessClass); tickets.put(AirlineTicketType.FIRST, firstClass); } }
Создайте конструктор для класса. В этом конструкторе функция вызова под названием «инициализация» создает начальные объекты. После создания исходного объекта добавьте в реестр следующие экземпляры авиабилетов. Наконец, создайте функции get для получения уже инициализированных авиабилетов.
Шаг 5.
Храните и извлекайте авиабилеты.
package PrototypeExample; public class Application { public static void main(String[] args) { Registry registry = new Registry(); EconomyClass economyClass = (EconomyClass) registry.getTicket(AirlineTicketType.ECONOMY); System.out.println("Initial Values........"); System.out.println("Economy Class: " + economyClass); economyClass.setFlightNumber("CX400"); economyClass.setDuration(0.0); economyClass.setDeparture("CMB"); economyClass.setArrival("HKG"); economyClass.setSeatNumber("CE14"); economyClass.setNeedAssistant(true); System.out.println("After Setting New Values........"); System.out.println("Economy Class: " + economyClass); EconomyClass economyClass1 = (EconomyClass) registry.getTicket(AirlineTicketType.ECONOMY); System.out.println("New Economy Class Instance Values........"); System.out.println("Economy Class: " + economyClass1); } }
Как видите, мы можем установить новые значения для авиабилетов и сохранить новые авиабилеты. А также при создании нового экземпляра из эконом-класса снова присваивается начальное значение, которое уже предоставлено из-за клонируемого интерфейса.
Преимущества шаблона проектирования прототипа:
· Разработчики могут избежать накладных расходов и проблем с производительностью процесса создания объекта.
Недостатки шаблона проектирования прототипа:
· Перебор для проекта, в котором используется очень мало объектов и/или не делается упор на расширение цепочек прототипов.
· Он также скрывает от клиента конкретные классы продуктов.
Я надеюсь, что теперь вы в состоянии понять, что такое шаблон проектирования прототипа, как реализовать шаблон проектирования прототипа и каковы его преимущества и недостатки.