组合模式
组合模式主要表现形式为树型结构,有一个整体和部分的关系,如我们平时使用的省份,县市,区县等
下面我们来看一个例子
这是一家餐厅的菜单结构,现在我们需要将其遍历输出
引入组合模式设计
对应代码
基类代码
package headfirst.hd.composite.eg;
public abstract class Component {
// 集合操作-增
public void add(Component menuComponent) {
throw new UnsupportedOperationException();
}
// 集合操作-删
public void remove(Component menuComponent) {
throw new UnsupportedOperationException();
}
// 集合操作-查
public Component getChild(int i) {
throw new UnsupportedOperationException();
}
public String getName() {
throw new UnsupportedOperationException();
}
public float getPrice() {
throw new UnsupportedOperationException();
}
public void print(int offset) {
throw new UnsupportedOperationException();
}
//偏移量,补空格使用
public void printOffsed(int offset) {
StringBuffer blank = new StringBuffer("");
for (int i = 0; i < offset; i++) {
blank.append(" ");
}
System.out.print(blank);
}
}
菜单项
package headfirst.hd.composite.eg;
//菜单项
public class Item extends Component {
private String name;
private float price;
public Item(String name, float price) {
this.name = name;
this.price = price;
}
@Override
public String getName() {
return name;
}
@Override
public float getPrice() {
return price;
}
@Override
public void print(int offset) {
super.printOffsed(offset);
System.out.println("[商品名=" + name + ", 价格=" + price + "]");
}
}
组合菜单
package headfirst.hd.composite.eg;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
//组合菜单
public class Menu extends Component {
List<Component> menuComponents = new ArrayList<Component>();
String name;
String description;
public Menu(String name, String description) {
this.name = name;
this.description = description;
}
@Override
public void add(Component menuComponent) {
menuComponents.add(menuComponent);
}
@Override
public void remove(Component menuComponent) {
menuComponents.remove(menuComponent);
}
@Override
public Component getChild(int i) {
return menuComponents.get(i);
}
@Override
public String getName() {
return name;
}
public String getDescription() {
return description;
}
@Override
public void print(int offset) {
super.printOffsed(offset);
System.out.println("{菜单名=" + name + ", 描述=" + description + "}");
ListIterator<Component> listIterator = menuComponents.listIterator();
while (listIterator.hasNext()) {
Component itemComponent = (Component) listIterator.next();
//递归思想
itemComponent.print(offset+1);
}
}
}
服务员代码
package headfirst.hd.composite.eg;
public class Waitress {
Component menu;
public Waitress(Component menu) {
this.menu = menu;
}
public void printMenu() {
menu.print(0);
}
}
测试代码
package headfirst.hd.composite.eg;
public class DriveTest {
public static void main(String[] args) {
Component menu = simpleFactory();
Waitress waitress = new Waitress(menu);
//打印菜单
waitress.printMenu();
}
//创建一份菜单
private static Component simpleFactory() {
//菜单
Component menu = new Menu("菜单", "xxx饭店菜单");
//菜单项
Component menuA = new Menu("饭类", "类别:主食类");
Component menuB = new Menu("水类", "类别:补充水分");
Component menuC = new Menu("小吃类", "类别:零食");
Component menuD = new Menu("汤类", "类别:水类的子类");
menu.add(menuA);
menu.add(menuB);
menu.add(menuC);
//菜单项中具体类别
Component itemA1 = new Item("牛肉", 15f);
Component itemA2 = new Item("鸡肉", 13f);
Component itemA3 = new Item("鸭肉", 14f);
menuA.add(itemA1);
menuA.add(itemA2);
menuA.add(itemA3);
Component itemB1 = new Item("红茶", 4f);
Component itemB2 = new Item("奶茶", 6f);
menuB.add(itemB1);
menuB.add(itemB2);
menuB.add(menuD); //菜单项的包含
Component itemC1 = new Item("烤翅", 8f);
Component itemC2 = new Item("尾虾", 8f);
Component itemC3 = new Item("鱿鱼", 5f);
menuC.add(itemC1);
menuC.add(itemC2);
menuC.add(itemC3);
Component itemD1 = new Item("菜汤", 6f);
Component itemD2 = new Item("酸汤", 6f);
Component itemD3 = new Item("其他汤", 5f);
menuD.add(itemD1);
menuD.add(itemD2);
menuD.add(itemD3);
return menu;
}
}
测试结果
{菜单名=菜单, 描述=xxx饭店菜单}
{菜单名=饭类, 描述=类别:主食类}
[商品名=牛肉, 价格=15.0]
[商品名=鸡肉, 价格=13.0]
[商品名=鸭肉, 价格=14.0]
{菜单名=水类, 描述=类别:补充水分}
[商品名=红茶, 价格=4.0]
[商品名=奶茶, 价格=6.0]
{菜单名=汤类, 描述=类别:水类的子类}
[商品名=菜汤, 价格=6.0]
[商品名=酸汤, 价格=6.0]
[商品名=其他汤, 价格=5.0]
{菜单名=小吃类, 描述=类别:零食}
[商品名=烤翅, 价格=8.0]
[商品名=尾虾, 价格=8.0]
[商品名=鱿鱼, 价格=5.0]
输出流程为
引入迭代器模式,改造以上代码的输出,减少类的责任
主要目的:减少类拥有的责任,比如这里是菜单项要负责管理集合操作,那么我们将输出操作转移到其他类中,属于面向对象原则的单一原则
多个Iterator的整合应用参考:https://blog.csdn.net/dengjili/article/details/79720730
栈思想
对应代码
package headfirst.hd.composite.eg2;
import java.util.Iterator;
public abstract class Component{
// 集合操作-增
public void add(Component menuComponent) {
throw new UnsupportedOperationException();
}
// 集合操作-删
public void remove(Component menuComponent) {
throw new UnsupportedOperationException();
}
// 集合操作-查
public Component getChild(int i) {
throw new UnsupportedOperationException();
}
public String getName() {
throw new UnsupportedOperationException();
}
public float getPrice() {
throw new UnsupportedOperationException();
}
public void print() {
throw new UnsupportedOperationException();
}
//增加迭代器,用于遍历
public Iterator<Component> createIterator() {
throw new UnsupportedOperationException();
}
}
package headfirst.hd.composite.eg2;
import java.util.Iterator;
//菜单项
public class Item extends Component {
private String name;
private float price;
public Item(String name, float price) {
this.name = name;
this.price = price;
}
@Override
public String getName() {
return name;
}
@Override
public float getPrice() {
return price;
}
@Override
public void print() {
System.out.println("[商品名=" + name + ", 价格=" + price + "]");
}
@Override
public Iterator<Component> createIterator() {
return new NullIterator();
}
}
package headfirst.hd.composite.eg2;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
//组合菜单
public class Menu extends Component {
List<Component> menuComponents = new ArrayList<Component>();
String name;
String description;
public Menu(String name, String description) {
this.name = name;
this.description = description;
}
@Override
public void add(Component menuComponent) {
menuComponents.add(menuComponent);
}
@Override
public void remove(Component menuComponent) {
menuComponents.remove(menuComponent);
}
@Override
public Component getChild(int i) {
return menuComponents.get(i);
}
@Override
public String getName() {
return name;
}
public String getDescription() {
return description;
}
@Override
public void print() {
System.out.println("{菜单名=" + name + ", 描述=" + description + "}");
}
//找出菜单项列表子类
public Iterator<Component> Iterators() {
return menuComponents.iterator();
}
@Override
public Iterator<Component> createIterator() {
return new CompositeIterator(this);
}
}
核心输出管理器
package headfirst.hd.composite.eg2;
import java.util.Iterator;
import java.util.Stack;
public class CompositeIterator implements Iterator<Component> {
Stack<Iterator<Component>> stack = new Stack<Iterator<Component>>();
public CompositeIterator(Component menu) {
stack.push(new IteratorAdapter(menu));
}
@Override
public boolean hasNext() {
//当前栈中没有迭代数据
if (stack.isEmpty()) {
return false;
}
//当前栈中有迭代数据
Iterator<Component> iterator = stack.peek();
//迭代数据中还有元素
if (iterator.hasNext()) {
return true;
}
//迭代数据中没有有元素,出栈
stack.pop();
return hasNext();
}
@Override
public Component next() {
//读取当前栈中的迭代器
Iterator<Component> iterator = stack.peek();
//取出元素
Component component = iterator.next();
//判断是菜单Menu类型
if (Menu.class.isAssignableFrom(component.getClass())) {
Menu menu = (Menu) component;
stack.push(menu.Iterators());
}
return component;
}
}
空迭代器
package headfirst.hd.composite.eg2;
import java.util.Iterator;
public class NullIterator implements Iterator<Component> {
@Override
public boolean hasNext() {
return false;
}
@Override
public Component next() {
return null;
}
}
首节点适配器
package headfirst.hd.composite.eg2;
import java.util.Iterator;
public class IteratorAdapter implements Iterator<Component> {
private boolean isIterator = false;
private Component componet = null;
public IteratorAdapter(Component componet) {
this.componet = componet;
isIterator = false;
}
@Override
public boolean hasNext() {
return !isIterator;
}
@Override
public Component next() {
Component temp = componet;
if (!isIterator) {
isIterator = true;
componet = null;
}
return temp;
}
}
服务员代码
package headfirst.hd.composite.eg2;
import java.util.Iterator;
public class Waitress {
Component menu;
public Waitress(Component menu) {
this.menu = menu;
}
public void printMenu() {
Iterator<Component> iterator = menu.createIterator();
while (iterator.hasNext()) {
Component component = iterator.next();
component.print();
}
}
}
测试类
package headfirst.hd.composite.eg2;
public class DriveTest {
public static void main(String[] args) {
Component menu = simpleFactory();
Waitress waitress = new Waitress(menu);
//打印菜单
waitress.printMenu();
}
//创建一份菜单
private static Component simpleFactory() {
//菜单
Component menu = new Menu("菜单", "xxx饭店菜单");
//菜单项
Component menuA = new Menu("饭类", "类别:主食类");
Component menuB = new Menu("水类", "类别:补充水分");
Component menuC = new Menu("小吃类", "类别:零食");
Component menuD = new Menu("汤类", "类别:水类的子类");
menu.add(menuA);
menu.add(menuB);
menu.add(menuC);
//菜单项中具体类别
Component itemA1 = new Item("牛肉", 15f);
Component itemA2 = new Item("鸡肉", 13f);
Component itemA3 = new Item("鸭肉", 14f);
menuA.add(itemA1);
menuA.add(itemA2);
menuA.add(itemA3);
Component itemB1 = new Item("红茶", 4f);
Component itemB2 = new Item("奶茶", 6f);
menuB.add(itemB1);
menuB.add(itemB2);
menuB.add(menuD); //菜单项的包含
Component itemC1 = new Item("烤翅", 8f);
Component itemC2 = new Item("尾虾", 8f);
Component itemC3 = new Item("鱿鱼", 5f);
menuC.add(itemC1);
menuC.add(itemC2);
menuC.add(itemC3);
Component itemD1 = new Item("菜汤", 6f);
Component itemD2 = new Item("酸汤", 6f);
Component itemD3 = new Item("其他汤", 5f);
menuD.add(itemD1);
menuD.add(itemD2);
menuD.add(itemD3);
return menu;
}
}
测试结果
{菜单名=菜单, 描述=xxx饭店菜单}
{菜单名=饭类, 描述=类别:主食类}
[商品名=牛肉, 价格=15.0]
[商品名=鸡肉, 价格=13.0]
[商品名=鸭肉, 价格=14.0]
{菜单名=水类, 描述=类别:补充水分}
[商品名=红茶, 价格=4.0]
[商品名=奶茶, 价格=6.0]
{菜单名=汤类, 描述=类别:水类的子类}
[商品名=菜汤, 价格=6.0]
[商品名=酸汤, 价格=6.0]
[商品名=其他汤, 价格=5.0]
{菜单名=小吃类, 描述=类别:零食}
[商品名=烤翅, 价格=8.0]
[商品名=尾虾, 价格=8.0]
[商品名=鱿鱼, 价格=5.0]
采用访问者改造
完全解耦
https://blog.csdn.net/dengjili/article/details/83540512