组合模式

组合模式

组合模式主要表现形式为树型结构,有一个整体和部分的关系,如我们平时使用的省份,县市,区县等

下面我们来看一个例子

这是一家餐厅的菜单结构,现在我们需要将其遍历输出
这里写图片描述

引入组合模式设计
这里写图片描述

对应代码

基类代码

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值