Java 中的無狀態對象
1. 概述
在本教程中,我們將討論如何在 Java 中實現無狀態對象。無狀態對像是沒有實例字段的類的實例。
在Java中,我們所有的代碼都必須放在一個類中。在編寫算法時,我們可能只需要在類中提供靜態方法即可實現此目的。
然而,有時我們可能希望將算法綁定到無狀態對象。
2. 關於狀態的對象概述
當我們考慮 Java 中的對象時,我們通常會想到在字段中包含狀態的對象,以及對該狀態進行操作以提供行為的方法。
最重要的是,我們可以創建具有不可修改字段的對象。它們的狀態在創建時定義,然後是不可變的,因為它們的狀態不會改變。在並發操作中,不可變對象受益於與無狀態對象相同的優點。
最後,我們的對像要麼根本沒有字段,要么只有編譯時常量字段。這些對像是無狀態的。
讓我們看看為什麼我們可能希望使用無狀態對象。
3. 使用無狀態對象
對於我們的示例,我們採用沒有狀態的排序算法。讓我們選擇冒泡排序作為我們的實現:
public void sort(int[] array) {
int n = array.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j array[j + 1]) {
int swap = array[j];
array[j] = array[j + 1];
array[j + 1] = swap;
}
}
}
}
3.1.多種無狀態排序實現
我們現在想要添加使用其他排序算法進行排序的可能性,因此我們考慮快速排序算法,它也是無狀態的:
public void sort(int[] array) {
quickSort(array, 0, array.length - 1);
}
private void quickSort(int[] array, int begin, int end) {
if (begin < end) {
int pi = partition(array, begin, end);
quickSort(array, begin, pi - 1);
quickSort(array, pi + 1, end);
}
}
private int partition(int[] array, int low, int high) {
int pivot = array[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (array[j] < pivot) {
i++;
int swap = array[i];
array[i] = array[j];
array[j] = swap;
}
}
int swap = array[i + 1];
array[i + 1] = array[high];
array[high] = swap;
return i + 1;
}
3.2.在實現之間進行選擇
假設使用哪種算法的決定是在運行時做出的。
我們需要一種在運行時選擇正確排序算法的方法。為此,我們使用一種稱為策略設計模式的設計模式。
為了在我們的例子中實現策略模式,我們將創建一個名為SortingStrategy
的接口,其中包含sort()
方法的簽名:
public interface SortingStrategy {
public void sort(int[] array);
}
現在,我們可以將每個排序策略實現為實現此接口的無狀態對象。這允許我們切換到我們喜歡的任何實現,而我們的消費代碼使用傳遞給它的任何排序對象:
public class BubbleSort implements SortingStrategy {
@Override
public void sort(int[] array) {
// Bubblesort implementation
}
}
public class QuickSort implements SortingStrategy {
@Override
public void sort(int[] array) {
// Quicksort implementation
}
// Other helpful methods
}
這裡我們的類不包含字段,因此沒有狀態。然而,既然有一個對象,它就可以滿足我們為所有排序算法定義的通用接口SortingStrategy
。
3.3.單例無狀態實現
我們想介紹一種為用戶提供所選排序策略的方法。由於這些類是無狀態的,因此我們不需要其中任何一個類的多個實例。因此,我們可以使用單例設計模式來做到這一點。
我們可以通過使用 Java enum
為策略實例實現此模式。
讓我們從class
類型切換到enum
並僅添加一個常量 - INSTANCE
。該常量實際上是該特定排序算法的單個無狀態實例。由於enum
可以實現 Java interface
,因此這是提供策略對象單例的一種巧妙方法:
public enum BubbleSort implements SortingStrategy {
INSTANCE;
@Override
public void sort(int[] array) {
// Bubblesort implementation
}
}
public enum QuickSort implements SortingStrategy {
INSTANCE;
@Override
public void sort(int[] array) {
// Quicksort implementation
}
// Other helpful methods
}
3.4.測試排序策略
最後,我們編寫測試以確保兩種排序策略都有效並且可以輕鬆維護:
@Test
void givenArray_whenBubbleSorting_thenSorted() {
int[] arrayToSort = {17, 6, 11, 41, 5, 3, 4, -9};
int[] sortedArray = {-9, 3, 4, 5, 6, 11, 17, 41};
SortingStrategy sortingStrategy = BubbleSort.INSTANCE;
sortingStrategy.sort(arrayToSort);
assertArrayEquals(sortedArray, arrayToSort);
}
@Test
void givenArray_whenQuickSortSorting_thenSorted() {
int[] arrayToSort = {17, 6, 11, 41, 5, 3, 4, -9};
int[] sortedArray = {-9, 3, 4, 5, 6, 11, 17, 41};
SortingStrategy sortingStrategy = QuickSort.INSTANCE;
sortingStrategy.sort(arrayToSort);
assertArrayEquals(sortedArray, arrayToSort);
}
4。結論
在本文中,我們探討了 Java 語言中的無狀態對象。
我們看到無狀態對像對於保持不需要狀態的算法很有用,我們還研究瞭如何實現策略模式。
像往常一樣,代碼片段可以在 GitHub 上找到。