这篇中,我们将看到一种不同于前两篇的状态模式设计方法。
状态切换器中自己维护了一张状态切换列表,而且不同的状态所执行的操作是一样的。
我们假设商品有多种不同的分类,每一种分类都会有不同的税收,例如商品包括食品、衣服、书等等,奢侈品会征收奢侈品税,香烟征收烟草税等等
代码结构:
商品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;
}
}
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();
}
}