Java中的空物件模式
為空或不是物件怎麼解決
今天,我正在討論一種較少使用的模式,稱為空物件模式。在面向物件的程式設計中,我們經常處理空物件。空物件是指沒有任何引用的物件或使用中性/空功能/行為定義的物件。在訪問任何成員或呼叫任何方法時,需要檢查這些空物件以確保它們不為空。這是因為成員或方法通常無法在空物件上呼叫。
空物件模式
空物件設計模式描述了空物件的用法及其在系統中的行為。
·
空物件模式處理空物件。
而不是檢查null物件,我們定義了null行為或呼叫了do-nothing行為。
這些空物件還可以用於在資料不可用的情況下提供預設行為。
這種方法優於有效的預設實現的優勢在於,空物件非常容易預測,並且沒有副作用-它 什麼也不做。
如果資源不可用於測試,則空物件模式還可以用作測試的存根。
在使用空物件模式之前,我們應該瞭解:
該模式應謹慎使用。它可以使錯誤顯示為正常程式執行。
我們不應該僅僅為了避免空檢查而使程式碼更具可讀性就實現這種模式。實際上,很難讀取移至另一個位置的程式碼,例如null物件類。
我們必須執行其他測試以確保沒有地方要分配null而不是null物件。
讓我們看一個例子,以更好地理解這種模式。
空物件的示例
建立一個抽象類(或介面)以指定各種功能。我在本示例中使用shape介面。請注意,我也在isNull() 介面中建立了一個方法 。有一個方法很好,而且我喜歡它,因為我可以更好地識別和控制空定義的物件。false 對於所有的
具體
類,此方法將返回 。並且,它將true 僅針對
空
物件類返回 。
package design。nullobject;
public interface Shape {
double area();
double perimeter();
void draw();
// nice to have method to indicate null object
boolean isNull();
}
您將需要建立一個擴充套件該類或實現該介面的具體類。每個具體的類都將定義功能的特定版本。我定義三種形狀: Circle , Rectangle ,和 Triangle。這些具體的類將定義不同型別的形狀。下面是Circle 該類的程式碼 :
public class Circle implements Shape {
// sides
private final double radius;
public Circle() {
this(1。0d);
}
public Circle(double radius) {
this。radius = radius;
}
@Override public double area() {
// Area = π r^2
return Math。PI * Math。pow(radius, 2);
@Override public double perimeter() {
// Perimeter = 2πr
return 2 * Math。PI * radius;
@Override public void draw() {
System。out。println(“Drawing Circle with area: ” + area() + “ and perimeter: ” + perimeter());
@Override
public boolean isNull() {
return false;
下面是Rectangle 該類的程式碼 :
public class Rectangle implements Shape {
// sides
private final double width;
private final double length;
public Rectangle() {
this(1。0d ,1。0d);
public Rectangle(double width, double length) {
this。width = width;
this。length = length;
public double area() {
// A = w * l
return width * length;
public double perimeter() {
// P = 2(w + l)
return 2 * (width + length);
@Override
public void draw() {
System。out。println(“Drawing Rectangle with area: ” + area() + “ and perimeter: ” + perimeter());
下面是Triangle 該類的程式碼 :
public class Triangle implements Shape {
// sides
private final double a;
private final double b;
private final double c;
public Triangle() {
this(1。0d, 1。0d, 1。0d);
public Triangle(double a, double b, double c) {
this。a = a;
this。b = b;
this。c = c;
// Using Heron‘s formula:
// Area = SquareRoot(s * (s - a) * (s - b) * (s - c))
// where s = (a + b + c) / 2, or 1/2 of the perimeter of the triangle
double s = (a + b + c) / 2;
return Math。sqrt(s * (s - a) * (s - b) * (s - c));
// P = a + b + c
return a + b + c;
System。out。println(“Drawing Triangle with area: ” + area() + “ and perimeter: ” + perimeter());
現在,最重要的步驟是建立一個空物件類,該物件類擴充套件了抽象類或介面並定義了“不執行操作”行為。萬一資料不可用,“不執行任何操作”行為就像預設行為。
public class NullShape implements Shape {
// no sides
return 0。0d;
System。out。println(“Null object can’t be draw”);
return true;
現在,我們定義 Factory 該類以建立各種型別的形狀。請參閱(Java中的策略vs工廠設計模式)以瞭解工廠模式。我ShapeFactory 為此示例建立 類。
public class ShapeFactory {
public static Shape createShape(String shapeType) {
Shape shape = null;
if (“Circle”。equalsIgnoreCase(shapeType)) {
shape = new Circle();
} else if (“Rectangle”。equalsIgnoreCase(shapeType)) {
shape = new Rectangle();
} else if (“Triangle”。equalsIgnoreCase(shapeType)) {
shape = new Triangle();
} else {
shape = new NullShape();
return shape;
為了使示例簡單,我沒有在ShapeFactory 方法中收到形狀邊的引數 。因此,工廠正在建立Shape 具有固定邊值的其他 物件。
並且,在最後一步,建立一個 Main 類來執行和測試程式碼:
import design。nullobject。ShapeFactory;
public class ShapeMain {
public static void main(String[] args) {
String[] shapeTypes = new String[] { “Circle”, null, “Triangle”, “Pentagon”, “Rectangle”, “Trapezoid”};
for (String shapeType : shapeTypes) {
Shape shape = ShapeFactory。createShape(shapeType);
// no null-check required since shape factory always creates shape objects
System。out。println(“Shape area: ” + shape。area());
System。out。println(“Shape Perimeter: ” + shape。perimeter());
shape。draw();
System。out。println();
}
下面是程式碼的輸出:
Shape area: 3。141592653589793
Shape Perimeter: 6。283185307179586
Drawing Circle with area: 3。141592653589793 and perimeter: 6。283185307179586
Shape area: 0。0
Shape Perimeter: 0。0
Null object can‘t be draw
Shape area: 0。4330127018922193
Shape Perimeter: 3。0
Drawing Triangle with area: 0。4330127018922193 and perimeter: 3。0
Shape area: 1。0
Shape Perimeter: 4。0
Drawing Rectangle with area: 1。0 and perimeter: 4。0
在Java 8中,我們具有 java。util。Optional 處理空引用的類。此類最初來自Guava API。
最後,開發這麼多年我也總結了一套學習Java的資料與面試題,如果你在技術上面想提升自己的話,可以關注我,私信傳送領取資料或者在評論區留下自己的聯絡方式,有時間記得幫我點下轉發讓跟多的人看到哦。