`

【转载】java设计模式—Null Object模式

阅读更多

相信大家一定在开发中见过并且写过类似这样的代码:

public Book getBook(int id) {
	if (id < 0) {
		return null;
	}
	return new Book(1, "Design Pattern", 100);
Book book = getBook(-1);
if (book != null) {
			
}

 

系统在使用对象的相关功能时,总要检查对象是否为null,如果不为null,我们才会调用它的相关方法,完成某种逻辑。这样的检查在一个系统中出现很多次,相信任何一个设计者都不愿意看到这样的情况。为了解决这种问题,我们可以可以引入空对象,这样,我们就可以摆脱大量程式化的代码,对代码的可读性也是一个飞跃。

等等,空对象是什么?它和null什么关系?

空对象是一个没有实质性内容的对象,但他并不为null。你可以把空对象理解为一个空箱子,这个物品还是存在的,只不过仅仅是一个壳,没有实质性的东西。

我们需要对原有的代码进行重构,把所有返回null的地方都替换成返回一个与之对应的空对象,然后再客户端调用时不再使用book==null这种方式判断是否为空,而是替换成book.isNull()的方式。下面我们就一步一步来实现这种模式。

首先,我们需要定义一个Nullable接口:

public interface Nullable {
	/**
	 * 对象是否为空
	 * @return
	 */
	public boolean isNull();
}

这个接口定义了一个isNull()的方法,来表示一个对象是否为空。

然后我们让Book实现此接口:

public class Book implements Nullable {

	private int id;
	private String name;
	private double price;
	
	public Book() {
	}
	
	public Book(int id, String name, double price) {
		this.id = id;
		this.name = name;
		this.price = price;
	}
	
	@Override
	public boolean isNull() {
		return false;
	}

	/**
	 * 创建一个NullBook实例代表空对象
	 * @return
	 */
	public static Book createNullBook() {
		return new NullBook();
	}
	
	/**
	 * setters & getters
	 */
}

Book中实现了isNull()方法,并返回false;另外Book还定义了一个静态的createNullBook方法,返回了一个NullBook的实例,NullBook是什么呢,我们来看一下:

public class NullBook extends Book {
	@Override
	public boolean isNull() {
		return true;
	}
}

NullBook继承了Book,并在isNull()方法中返回true,这个NullBook其实就是我们上面提到的空对象,仅仅是个空箱子而已。

然后我们定义一个BookService类,用以模拟获取Book的接口方法:

public class BookService {
	public Book getBook(int id) {
		if (id < 0) {
			//返回一个空对象
			return Book.createNullBook();			
		}
		return new Book(id, "Design Pattern", 100);
	}
}

getBook(int id)中,如果id<0时,则返回一个NullBook的实例,在客户端调用isNull()方法时则返回true,表示是空对象;如果id>=0时,则返回一个Book的实例,在客户端调用isNull()方法时则返回false,表示对象不为空,可以调用相关方法取得数据。对于我们的客户端来讲,返回的都是一个Book类型的对象,我们并不清楚返回的到底是真正的Book实例还是空对象NullBook实例,但是我们并不担心,因为有一点可以肯定的是,我们都可以放心的调用isNull()方法,因为它会根据运行期对象的类型返回一个正确的值。

多态的最根本好处在于:你不必再向对象询问你是什么类型而后根据得到的答案调用对象的某个行为,你只管调用该行为就是了,其他的一切事情多态机制会为你妥善处理。

最后再来看一下客户端是如何实现对象为空的判断的:

public class Client {
	public static void main(String[] args) {
		BookService service = new BookService();
		Book book = service.getBook(-1);
		if (book.isNull()) {
			System.out.println("not found!");
		} else {
			System.out.println("name:" + book.getName());
			System.out.println("price:" + book.getPrice());
		}
	}
}

除了定义isNull()之外,我们还可以使用另外一种方式来完成检查对象是否为null”的功能。

我们需要先定义一个Null接口,这个接口不需要定义任何方法,仅仅是标志着对象是否为空对象:

public interface Null {
}

然后我们的Book类现在不再需要实现任何接口了,它仅仅是一个普通的JavaBean,我们只需新增一个这样的NullBook类:

public class NullBook extends Book implements Null{
}

修改相应的方法:

public Book getBook(int id) {
		if (id < 0) {
			//返回一个空对象
			return new NullBook();			
		}
		return new Book(id, "Design Pattern", 100);
}

然后在客户端这样使用:

if (book instanceof NullBook) {
			
}

通常,不在万不得已的情况下,我们应该尽量避免使用instanceof操作符,但在这种情况下,我们也提倡使用它,因为这种做法有一个好处就是,不需要修改Book源码,这么一来,即使无法修改Book,我们也可以使用空对象。

 

分享到:
评论

相关推荐

    33种JAVA设计模式DEMO

    这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。 工厂模式(Factory Pattern) 抽象工厂模式...

    用Java实现23种设计模式

    用Java实现23种设计模式 1. 创建型模式 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern)...

    java常用设计模式及JDK与CGLIB实现动态代理区别(源码)

    java常用设计模式及JDK与CGLIB实现动态代理区别(源码) /** * 使用cglib动态代理 * @author * */ public class BookFacadeProxy implements MethodInterceptor{ private Object target; @Override public...

    java常用设计模式-空对象模式

    空对象模式(Null Object Pattern)是一种行为设计模式,它允许我们在不返回 null 的情况下提供默认行为。这种模式通常用于需要处理 null 对象的情况下,以避免NullPointerException 异常。 在软件设计中,我们经常...

    23种java版设计模式源码案例.zip

    23种java版设计模式源码案例.zip 0.目录 创建型模式(creational) 简单工厂(simplefactory) 动态工厂(dynamic) 抽象工厂(abstract) 单例模式(singleton) 建造者模式(builder) 原型模式(prototype) 结构型模式...

    二十三种设计模式【PDF版】

    所以很少存在简单重复的工作,加上Java 代码的精炼性和面向对象纯洁性(设计模式是 java 的灵魂),编程工作将变成一个让你时刻 体验创造快感的激动人心的过程. 为能和大家能共同探讨"设计模式",我将自己在学习中的心得...

    Java常用的3中设计模式代码即工厂模式、单例模式、观察者模式demo

    Java中,有23种GOF(Gang of Four)设计模式,分为创建型、结构型和行为型三大类。今天我们将聚焦于其中的三种:工厂模式、单例模式和观察者模式。 **1. 工厂模式** 工厂模式是一种创建型设计模式,它提供了一种...

    JAVA面试设计模式.ppt

    在Java面试中,设计模式是衡量开发者能力的重要标准,因为它们能够提高代码的可读性、可维护性和复用性。以下是根据提供的内容对几种常见设计模式的详细说明: 1. **Singleton(单例模式)**: - 单例模式确保一个...

    java设计模式(收集整理,学习笔记)

    Java设计模式是软件开发中的一种重要思想,它是一种在特定情境下解决常见问题的模板,可以提高代码的可重用性、可维护性和灵活性。在Java中,设计模式主要分为三大类:创建型、结构型和行为型。下面将详细讨论在给定...

    Java单例模式设计

    Java单例模式是一种常用的设计模式,它保证一个类只有一个实例,并提供全局访问点。这种模式在需要频繁创建和销毁对象的场景中,或者当对象昂贵时(如数据库连接),能够节省系统资源,提高效率。本篇文章将深入探讨...

    java设计模式之单例模式

    Java设计模式中的单例模式是一种常用的创建型设计模式,它保证了类只有一个实例,并提供一个全局访问点。这种模式在很多场景下非常有用,比如控制共享资源、管理配置信息等。接下来,我们将深入探讨8种不同的单例...

    实例讲解Java设计模式编程中如何运用代理模式共3页.pd

    总结来说,代理模式是Java设计模式中的重要一环,它提供了扩展和控制对象行为的能力。无论是静态代理还是动态代理,都能够帮助我们在不触及核心业务代码的前提下,实现功能增强和控制。理解并熟练运用代理模式,对于...

    Java 单例模式 工具类

    Java中的单例模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供全局访问点。在Java编程中,单例模式常用于控制资源的访问,比如数据库连接池、线程池或者日志对象等。本篇文章将深入探讨如何在Java中...

    JAVA操作数据库方式与设计模式应用.txt

    ### Java操作数据库方式与设计模式应用 #### 一、Java操作数据库基础:JDBC **JDBC(Java Database Connectivity)**是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写...

    从房屋买卖看 java proxy 模式

    总的来说,Java 代理模式是通过代理类来增强或扩展目标类功能的一种设计模式,尤其适用于需要在调用前后添加额外逻辑的场景。通过深入理解代理模式和其在房屋买卖场景中的应用,我们可以更好地掌握这一重要的设计...

    超市管理系统java源码swing-king-design:23种java设计模式

    设计模式 0.目录 创建型模式(creational) 简单工厂(simplefactory) 动态工厂(dynamic) 抽象工厂(abstract) 单例模式(singleton) 建造者模式(builder) 原型模式(prototype) 结构型模式(structure) 适配器模式(adaptor...

    我们的设计模式(绝对通俗易懂)

    ### 设计模式——通俗易懂的解读 #### 引言 设计模式是在软件工程领域内广泛应用的一种编程思想,它能够帮助开发者解决常见的编程难题,并提供一套成熟、经过验证的解决方案。设计模式通常被分为三大类:创建型...

    java设计模式之Flyweight[归纳].pdf

    Java设计模式中的Flyweight模式是一种结构型模式,其主要目的是减少对象的数量,通过共享大量具有相似属性的对象来节省内存和提高性能。Flyweight模式的核心思想是区分对象的内部状态(intrinsic state)和外部状态...

    Java面向对象(高级)- 单例(Singleton)设计模式

    《设计模式:可复用面向对象软件的基础》(Design Patterns: Elements of Reusable Object-Oriented Software)是设计模式领域的经典著作,由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位作者合著...

    Java Monitor Pattern设计模式

    Java 监视器模式(Java Monitor Pattern)是一种用于多线程环境中的设计模式,它主要依赖于Java语言的同步机制,如`synchronized`关键字和`wait()`, `notify()`等方法,来确保线程安全和资源的有序访问。在Java中,...

Global site tag (gtag.js) - Google Analytics