状态模式的具体实现 情景三

这篇中,我们将看到一种不同于前两篇的状态模式设计方法。

状态切换器中自己维护了一张状态切换列表,而且不同的状态所执行的操作是一样的。

我们假设商品有多种不同的分类,每一种分类都会有不同的税收,例如商品包括食品、衣服、书等等,奢侈品会征收奢侈品税,香烟征收烟草税等等

代码结构:


商品Goods类:

package com.anvien.practice.state_one;

import java.util.HashSet;
import java.util.Set;
/**
 * 商品
 */
public class Goods {
	/** 名称 */
	private String name;
	/** 单价 */
	private double price;
	/** 分类集合,一种商品在不同的分类标准下,可能会属于多种分类  */
	Set<Category> categories = new HashSet<Category>();
	
	/**
	 * 构造方法
	 * @param name
	 * 		名称
	 * @param price
	 * 		单价
	 */
	public Goods(String name, double price)
	{
		this.name = name;
		this.price = price;		
	}

	/**
	 * 获取商品名称
	 * @return
	 * 		商品名称
	 */
	public String getName() {
		return name;
	}

	/**
	 * 设置商品名称
	 * @param name
	 * 		商品名称
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * 获取商品单价
	 * @return
	 * 		商品单价
	 */
	public double getPrice() {
		return price;
	}

	/**
	 * 设置商品单价
	 * @param price
	 * 		商品单价
	 */
	public void setPrice(double price) {
		this.price = price;
	}

	/**
	 * 为商品添加新的分类
	 * @param category
	 * 		新的分类
	 * @return
	 * 		返回添加成功与否
	 */
	public boolean addCategory(Category category)
	{
		return this.categories.add(category);
	}
	
	/**
	 * 获取商品的分类集合
	 * @return
	 * 		商品的分类集合
	 */
	public Set<Category> getCategories()
	{
		return this.categories;
	}
}


税收Tax类:

package com.anvien.practice.state_one;

/**
 * 税务
 *
 */
public class Tax {
	/** 名称 */
	private String name;
	/** 税率 */
	private double rate;
	
	public Tax(String name, double rate)
	{
		this.name = name;
		this.rate = rate;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getRate() {
		return rate;
	}

	public void setRate(double rate) {
		this.rate = rate;
	}

	@Override
	public String toString() {
		return "Tax [name=" + name + ", rate=" + rate + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		long temp;
		temp = Double.doubleToLongBits(rate);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Tax other = (Tax) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (Double.doubleToLongBits(rate) != Double
				.doubleToLongBits(other.rate))
			return false;
		return true;
	}

}


分类:
package com.anvien.practice.state_one;

import java.util.HashSet;
import java.util.Set;

/**
 * 商品类别
 *		
 */
public class Category {

	/** 当前类别所包含的商品关键字集合,即商品中包含列表中的某一项关键字的话,商品就属于这种类别的。*/
	protected Set<String> contentSet = new HashSet<String>();
	/** 当前类别所包含的税收集合。*/
	protected Set<Tax> taxSet = new HashSet<Tax>();
	/**
	 * 商品执行分类操作的启动方法
	 * @param classifier
	 * 		将要对商品进行分类的分类器
	 */
	public void classify(Classifier classifier)
	{
		if(contentSet.contains(classifier.getGoods().getName()) || classifier.isLastCategory())
		{
			classifier.getGoods().addCategory(classifier.getCurrentCategory());
		}
		else
		{
			classifier.classify();
		}
	}
	
	/**
	 * 设置当前类别的内容关键字列表
	 * @param list
	 * 		内容关键字列表
	 */		
	public void setContentSet(Set<String> set)
	{
		this.contentSet = set;
	}
	
	/**
	 * 获取当前类别的内容关键字列表
	 * @return
	 * 		内容关键字列表
	 */
	public Set<String> getContentSet()
	{
		return this.contentSet;
	}
	
	/**
	 * 向当前税收集合中添加一种新的税收
	 * @param tax
	 * 		新的税收
	 * @return
	 * 		返回税收添加成功与否
	 */
	public boolean addTax(Tax tax)
	{
		return this.taxSet.add(tax);
	}
	
	/**
	 * 获取当前类别的税收集合
	 * @return
	 * 		税收集和
	 */		
	public Set<Tax> getTaxSet() {
		return taxSet;
	}
}

分类器:

package com.anvien.practice.state_one;


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


/**
 * 分类器, 用于检查当前商品在指定分类集合中的所属情况
 *
 */
public class Classifier {
	private Goods goods;
	private List<Category> categoryList;
	int indicator = -1;
	/**
	 * 构造方法
	 * @param categoryList
	 * 		分类集合
	 * 		注意集合中的最后一项分类为默认分类,
	 * 		即商品都不属于集合中的前面分类时,会被归纳为最后一个分类
	 */
	public Classifier(List<Category> categoryList) {
		this.categoryList = categoryList;
	}
	/**
	 * 构造方法
	 * @param categorys
	 * 		分类集合
	 * 		注意集合中的最后一项分类为默认分类,
	 * 		即商品都不属于集合中的前面分类时,会被归纳为最后一个分类
	 */
	public Classifier(Category... categorys)
	{
		this.categoryList = new ArrayList<Category>();
		for(Category c : categorys)
		{
			this.categoryList.add(c);
		}
	}
	/**
	 * 返回分类器正在处理的商品
	 * @return
	 * 		返回分类器当前执行分类的商品
	 */
	public Goods getGoods() {
		return goods;
	}
	/**
	 * 设置分类器将要执行分类的商品
	 * @param goods
	 * 		将要执行分类的商品
	 */
	public void setGoods(Goods goods) {
		this.goods = goods;
		this.indicator = -1;
	}
	/**
	 * 获取分类集合
	 * @return
	 * 		分类集合
	 */
	public List<Category> getCategoryList() {
		return categoryList;
	}
	/**
	 * 设置分类集合
	 * @param categoryList
	 * 		分类集合
	 */
	public void setCategoryList(List<Category> categoryList) {
		this.categoryList = categoryList;
	}
	/**
	 * 返回分类器当前得到的类别
	 * @return
	 * 		当前得到的类别
	 */
	public Category getCurrentCategory()
	{
		if(this.categoryList == null || this.indicator > this.categoryList.size()-1)
		{
			return null;
		}
		return this.categoryList.get(this.indicator);
	}
	
	/**
	 * 返回分类器是否已经在检查最后一种类别
	 * @return
	 * 		是否已经在检查最后一种类别
	 */
	public boolean isLastCategory()
	{
		if(this.categoryList == null || this.categoryList.size() < 1 
				|| this.indicator >= this.categoryList.size()-1)
		{
			return true;
		}
		return false;
	}
	
	/**
	 * 分类器执行类别检查的启动方法
	 */
	public void classify()
	{
		this.indicator++;
		getCurrentCategory().classify(this);
	}
}


测试:

package com.anvien.practice.state_one;

public class Main {

	public static void main(String[] args) {
		Goods book = new Goods("notebook", 5.0);
		Goods food = new Goods("food", 12);
		
		Tax foodTax = new Tax("food tax", 0.1);
		Category foodCategory = new Category();
		foodCategory.addTax(foodTax);
		
		Tax bookTax = new Tax("book tax", 0.2);
		Category bookCategory = new Category();
		bookCategory.addTax(bookTax);
		
		Category otherCategory = new Category();
		
		Classifier clsfr = new Classifier(foodCategory, bookCategory, otherCategory);
		clsfr.setGoods(food);
		clsfr.classify();
		clsfr.setGoods(book);
		clsfr.classify();
		
	}
}


这种方法看起来不像是状态模式的,但其实思想还是最基本的状态模式思想。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值