java 空对象_Java中的空对象模式

今天,我正在讨论一种较少使用的模式,称为空对象模式。在面向对象的编程中,我们经常处理空对象。空对象是指没有任何引用的对象或使用中性/空功能/行为定义的对象。在访问任何成员或调用任何方法时,需要检查这些空对象以确保它们不为空。这是因为成员或方法通常无法在空对象上调用。

4abe9e1e069f2bacab583703b2a7db97.png

空对象模式

空对象设计模式描述了空对象的用法及其在系统中的行为。

·

空对象模式处理空对象。

而不是检查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的资料与面试题,如果你在技术上面想提升自己的话,可以关注我,私信发送领取资料或者在评论区留下自己的联系方式,有时间记得帮我点下转发让跟多的人看到哦。

7c264a115645164b9639100499bf0a94.png

d55fe0168f6765582df64c1f297e15a5.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值