朋友不要让朋友使用字符串状态

我的许多同事都介绍了激动人心的新技术和框架,以帮助您提高编程专业知识。 但是目前,我认为重要的是回头并涵盖一个重要的编程基础。 在我的整个编程生涯中,我所见过的最常见的反模式之一就是“字符串状态”。 在我从事的每个项目中,它都以某种形式出现。 简而言之,“字符串状态”反模式是使用Java字符串表示对象的状态。 当然,状态的字符串表示很重要。 您希望代码是可读的,想要数据库中报表的值可读,并且希望用户可读的状态表示形式呈现在界面上。 所有这些都是好东西,您应该使用状态的某种字符串表示形式,但是不要让string成为状态的整个实现。 以这个购物车的简化版本为例:

package stringstate;

public class Item {
	private String name;
	private int price;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
}

package stringstate;

public interface OrderState {
	public static String OPEN = "Open";
	public static String CLOSED = "Closed";
}

package stringstate;

import java.util.ArrayList;
import java.util.List;

public class Order extends Item implements OrderState {
	private List items = new ArrayList();
	private String orderState;

	public List getItems() {
		return items;
	}

	protected  void setItems(List items) {
		this.items = items;
	}

	public String getOrderState() {
		return orderState;
	}

	public void setOrderState(String orderState) {
		this.orderState = orderState;
	}

	public void addItem(Item anItem){
		getItems().add(anItem);
	}

}

在此示例中,状态不用于任何业务逻辑。 在这种情况下,字符串状态不会有害。 但是,没有一个项目会如此简单。 即使状态仅以显示/存储开始,您最终还是会将其用于业务逻辑。 相信我-如果对象的状态足以存储,那么最终您将不得不做出决定。 因此,现在您过于简化的购物车需要防止人们在关闭时添加商品。 简单:添加新方法并修改addItem

public void addItem(Item anItem){
		if (canModify()){
			getItems().add(anItem);
		} else {
			throw new IllegalStateException("Cannot add items to a closed order");
		}
	}

	public boolean canModify(){
		return getOrderState().equals(OPEN);
	}

到目前为止还不错。 为什么我对您要求的字符串状态这么不满意? 因为现在您要添加2个新状态“ 新建”和“已完成”,并为用户提供重新打开未完成订单的选项。 当然,一种新的方法,一个修改canModify,setOrderState检查,我们对我们的方式。 但是,等等,现在用户想要2个完成状态: 发货已取消 。 再进行一些调整,对吗? 现在,您的订单代码中充斥着与状态有关的“ if语句”:

package stringstate;

import java.util.ArrayList;
import java.util.List;

public class Order extends Item implements OrderState {
	private List items = new ArrayList();
	private String orderState;

	public List getItems() {
		return items;
	}

	protected  void setItems(List items) {
		this.items = items;
	}

	public String getOrderState() {
		return orderState;
	}

	public void setOrderState(String orderState) {
		if (!isFinalized()){
			this.orderState = orderState;
		}
	}

	public void addItem(Item anItem){
		if (canModify()){
			getItems().add(anItem);
		} else {
			throw new IllegalStateException("Cannot add items to a closed order");
		}
	}

	public boolean canModify(){
		return getOrderState().equals(OPEN);
	}

	public void reOpen(){
		if (!isFinalized()){
			setOrderState(OPEN);
		}
	}

	public boolean isFinalized(){
		return getOrderState().equals(SHIPPED) || getOrderState().equals(CANCELED);
	}
}

糟糕,我们忘记将新状态添加到canModify() 。 现在以策略状态为例,其中所有状态逻辑都委派给比字符串更智能的对象。 第一个好处是使所有逻辑与订单有关,而不是与订单状态有关。 下一个好处是,只要您基于状态添加新决策,就可以抽象地实施该决策,以强制在所有状态下实施或提供默认实施。 订购:

package strategystate;

import java.util.ArrayList;
import java.util.List;

public class Order {
	private List items = new ArrayList();
	private OrderState orderState;

	public List getItems() {
		return items;
	}

	protected  void setItems(List items) {
		this.items = items;
	}

	public OrderState getOrderState() {
		return orderState;
	}

	public void setOrderState(OrderState orderState) {
		if (!getOrderState().isFinalized()){
			this.orderState = orderState;
		}
	}

	public void addItem(Item anItem){
		if (getOrderState().canModify()){
			getItems().add(anItem);
		} else {
			throw new IllegalStateException("Cannot add items to a closed order");
		}
	}

	public void reOpen(){
		if (!getOrderState().isFinalized()){
			setOrderState(OrderState.OPEN);
		}
	}

}

public enum OrderState {
	NEW("New",true,false),
	OPEN("Open",true,false),
	CLOSED("Closed",false,false),
	SHIPPED("Shipped",false,true),
	CANCELED("Canceled",false,true);

	protected String name;
	protected boolean finalized;
	protected boolean modify;

	private OrderState(String name, boolean canModify, boolean isFinalized){
		this.name = name;
		this.finalized= isFinalized;
		this.modify = canModify;
	}
	public boolean canModify(){
		return modify;
	}
	public boolean isFinalized(){
		return finalized;
	}
	public String getName(){
		return name;
	}
}

状态越多,基于状态的逻辑越多,则从策略状态中获得的收益就越大。 策略状态使您的主要业务对象免受基于状态列表的增长的“ if语句”的影响。 另外,您还可以保留字符串的所有便利。 在此示例中,差异可能很小,但是随着域复杂性的增加,策略状态的好处也会增加。 另外,您曾经在复杂性没有增长的地方从事过哪个项目? 我的建议是始终从策略状态开始。 开销很小,随着项目复杂度的提高,您将感激不尽。

参考: Keyhole Software博客中的“ 朋友不要让朋友使用我们的JCG合作伙伴 Brad Mongar的字符串状态”

翻译自: https://www.javacodegeeks.com/2013/07/friends-dont-let-friends-use-string-states.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值