1. Что такое шаблон дизайна
В разработке программного обеспечения дизайн шаблон является решением, предложенным для различных общих (повторяющихся) задач в области проектирования программного обеспечения. Этот термин был введен в информатику из области архитектурного дизайна в 1990 -х годах Эрихом Гаммой и другими.
Знаменитая банда из 4 человек: Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссис (GOF)
Образец дизайна: основы многоразового объектно-ориентированного программного обеспечения
2. Синглтон режим
Класс объекта Singleton должен быть гарантированно иметь только один экземпляр. Много раз вся система должна иметь только один глобальный объект, который способствует нашей координации общего поведения системы.
Например: конфигурация глобальной информации
Самая простая реализация режима синглтона:
открытый класс Singleton {private singleton () {System.out.println ("singleton is create"); } Частный статический экземпляр Singleton = new Singleton (); public static singleton getInstance () {return ancess; }} Уникальность определяется частным конструктором и статичным.
Недостатки: когда генерируется экземпляр, трудно контролировать
Хотя мы знаем, что когда класс синглтон сначала загружен, генерируется экземпляр.
Но если в этом классе есть другие свойства
открытый класс Singleton {public static int status = 1; private singleton () {System.out.println ("singleton is create"); } Частный статический экземпляр Singleton = new Singleton (); public static singleton getInstance () {return ancess; }} При использовании
System.out.println (singleton.status);
Этот пример произведен. Может быть, вы не хотите, чтобы этот экземпляр генерировался в настоящее время.
Если система уделяет особое внимание этой проблеме, метод реализации этого Синглтона не очень хорош.
Решение второго режима синглтона:
открытый класс Singleton {private singleton () {System.out.println ("singleton is create"); } Частный статический экземпляр синглтона = null; public static synchronized singleton getInstance () {if (exance == null) encement = new Singleton (); вернуть экземпляр; }} Пусть экземпляр создается только при вызове метода getInstance (), и безопасность потока обеспечивается с помощью синхронизации.
Это управляет при создании экземпляров.
Этот подход типичен для ленивой нагрузки.
Но одна из проблем заключается в том, что производительность окажет влияние на сценарии высоких параллелей. Несмотря на то, что он возвращается только одним суждением, оно окажет влияние в случае высокого параллелизма, оно будет иметь более или меньшее влияние, поскольку вы должны получить синхронизированный блокировка.
Чтобы быть эффективным, есть третий метод:
Public Class Statsicingleton {Private StatsicingLeton () {System.out.println ("statsicingleton - это создание"); } Частный статический класс Singletonholder {Private Static Staticing Encament = new StatsicingLeton (); } public staticsingLeton getInstance () {return singletonholder.instance; }} Поскольку, когда класс загружается, его внутренний класс не будет загружен. Это гарантирует, что экземпляр будет генерироваться только при вызове getInstance (), время генерации экземпляра контролируется, и достигается отсроченная нагрузка.
И синхронизированный удаляется, чтобы улучшить производительность, а статический используется для обеспечения уникальности.
3. Инвариантный режим
После создания внутреннего состояния класса оно не изменится в течение всего периода жизни.
Режим Unchange не требует синхронизации
Создайте неизменный класс:
Public Final Class Product {// Убедитесь, что нет подкласса частной финальной строки №; // частные атрибуты не будут получены другими объектами частным именем окончательной строки; // окончание гарантирует, что атрибут не будет назначен дважды частной двойной цены; Публичный продукт (строка №, имя строки, двойная цена) {// При создании объекта данные должны быть указаны Super (); // Потому что после создания его нельзя изменить это. No = no; this.name = name; this.price = цена; } public String getNo () {return no; } public String getName () {return name; } public Double GetPrice () {return Price; }} Случаи неизменных моделей в Java включают:
java.lang.string
java.lang.boolean
java.lang.byte
java.lang.character
java.lang.double
java.lang.float
java.lang.integer
java.lang.long
java.lang.short
4. Будущий режим
Основная идея - асинхронные вызовы
Несинхронно:
асинхронный:
Первый Call_return возвращается, поскольку задача еще не была выполнена.
Но это возвращение похоже на заказ в покупке, и вы можете получить результат на основе этого порядка в будущем.
Таким образом, эта будущая модель означает, что «будущее» может быть получено, что означает, что порядок или контракт являются «обещанием» и дадут результат в будущем.
Простая реализация будущего режима:
Абонент получает данные, которые вначале могут быть фантастическими, потому что realdata медленно строит. В какое -то время в будущем Realdata может быть получена через Futuredata.
Реализация кода:
Данные публичного интерфейса {public String getResult (); } public Class futuretata реализует данные {защищенные realdata realdata = null; // Futuredata - это булево -защищенная обертка Realdata, защищенная от обертки, не False; public Synchrinized void setReAldata (realdata realdata) {if (issready) {return; } this.Realdata = realdata; isReady = true; notifyAll (); // realdata был введен, уведомляет getResult ()} public synchronized String getResult () // ждать завершения конструкции Realdata {while (! Isrede) {try {wait (); // ждать все время, чтобы узнать, что realdata вводится} catch (прерывание Exception e) {}} return realdata.result; // реализовано realdata}} открытый класс Realdata реализует данные {защищенный результат окончательной строки; Public Realdata (String Para) {// Конструкция Realdata может быть очень медленной и требует, чтобы пользователь долго ждал. Здесь мы используем сон для моделирования StringBuffer SB = new StringBuffer (); for (int i = 0; i <10; i ++) {sb.append (para); Попробуйте {// использовать сон здесь вместо очень медленной эксплуатации. Sleep (100); } catch (прерывание Exception e) {}} result = sb.toString (); } public String getResult () {return Result; / new Thread () {public void run () {// realData очень медленно строить, // SO Realdata в отдельном потоке realdata = new Realdata (Querystr); Future.setRealdata (realdata); } } }.начинать(); вернуть будущее; // futuredata будет возвращена немедленно}} public static void main (string [] args) {client client = new Client (); // это будет возвращено немедленно, потому что то, что вы получаете, является Futureata вместо data Data Data = client.request ("name"); System.out.println ("запрос завершен"); Попробуйте {// Здесь вы можете использовать сон вместо обработки другой бизнес -логики // В процессе обработки этой бизнес -логики создается Realdata, в полной мере используя The Thread Time.ssepe (2000); } catch (прерывание Exception e) {} // Использовать реальные данные данных. }Есть также много поддержки в будущем в JDK:
Далее используйте классы и методы, предоставленные JDK для реализации кода только сейчас:
Import java.util.concurrent.callable; открытый класс realdata реализует Callable <string> {Private String para; public realdata (String para) {this.para = para; } @Override public String Call () Throws Exception {StringBuffer sb = new StringBuffer (); for (int i = 0; i <10; i ++) {sb.append (para); try {thread.sleep (100); } catch (прерывание Exception e) {}} return sb.toString (); }} Импорт java.util.concurrent.executionexception; import java.util.concurrent.executorservice; import java.util.concurrent.executors; import java.util.concurrent.futureTas FutureTask futureTask <string> future = new FutureTask <string> (new Realdata ("a")); Executorservice executor = executors.newfixedthreadpool (1); // Выполнить FutureTask, эквивалентный Client.Request ("a") в приведенном выше примере Отправить запрос // Включить поток здесь, чтобы выполнить realdata call () и выполнить executor.submit (future); System.out.println ("запрос завершен"); TRY {// Дополнительные операции данных все еще могут быть выполнены здесь, и сон можно использовать вместо обработки другой бизнес -логики. Sleep (2000); } catch (прерывание Exception e) {} // эквивалентно data.getResult (), получите возвращаемое значение метода Call () // Если метод Call () не выполнен в настоящее время, он все равно будет ждать System.out.println ("data =" + future.get ()); }} Здесь нужно отметить, что FutureTask - это класс, который имеет будущую функцию и выполняемую функцию. Так что он может работать снова и, наконец, получить это.
Конечно, если реальные данные не будут готовы при вызове Future.get (), это все равно вызовет ситуацию блокировки до тех пор, пока данные не будут готовы.
Конечно, есть более простые способы:
import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class FutureMain2 { public static void main(String[] args) throws InterruptedException, ExecutionException { ExecutorService executor = Исполнители.newfixedThreadpool (1); // Выполнить FutureTask, эквивалентный client.request («a») в приведенном выше примере Отправить запрос // Откройте поток здесь, чтобы выполнить realdata call () и выполнить будущее <string> future = executor.submit (new Realdata («a»)); System.out.println ("запрос завершен"); Try {// Дополнительные операции данных все еще могут быть выполнены здесь, используйте сон вместо другой поток обработки бизнес -логики. Sleep (2000); } catch (прерывание Exception e) {} // эквивалентно data.getResult (), получите возвращаемое значение метода Call () // Если метод Call () не выполняется в это время, System.out.println все равно будет ждать system.out.println ("data =" + future.get ()); }} Поскольку Callible имеет возвратное значение, вы можете напрямую вернуть будущий объект.
5. Производитель и потребитель
Модель продюсера-потребителя представляет собой классическую многопоточную модель дизайна. Это обеспечивает хорошее решение для сотрудничества между несколькими потоками. В модели производителя-потребителя обычно существует два типа потоков, а именно несколько потоков производителей и несколько потребительских потоков. Поток производителя несет ответственность за отправку запросов пользователей, в то время как потребительский поток отвечает за специально выполнение задач, представленных производителем. Производитель и потребитель общаются через общий буфер памяти.
В прошлом я писал статью для реализации различных методов использования Java для реализации производителей и потребителей, поэтому я не буду объяснять ее здесь.