HeadFirst 设计模 4000 式 9迭代器与组合模式(餐厅合并)
2015-08-17 13:55
447 查看
迭代器模式
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
迭代器模式让我们能够游走于聚合内的每个元素,而又不暴露其内部的表示。把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。
集合collection/聚合aggregate:指一群对象,其存储方法可以是各式各样的数据结构,例如:列表、数组、散列表,无论用什么方式存储,一律可以视为是集合/聚合。
实例:
public class MenuItem{
String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name,String description,boolean vegetarian,double price){
this.name=name;
this.description=description;
this.vegetarian=vegetarian;
this.price=price;
}
public String getName(){ return name;}
public String getDescription(){ return description;}
public double getprice(){ return price;}
public boolean isVegetarian(){ return vegetarian;}
}
public interface Iterator{
boolean hasNext(); //返回一个布尔值,判断是否还有更多的元素
Object next(); //返回下一个元素
}
//实现迭代器接口 DinerMenu
public class DinerMenuIterator implements Iterator{
MenuItem[] items;
int position = 0; //position记录当前数组遍历的位置
public DinerMenuIterator(MenuItem[] items){ //构造器需要被传入一个菜单项的数组当作参数
this.items=items;
}
public Object next(){ //返回数组内的下一项,并递增其位置
MenuItem menuItem= items[position];
position=position+1;
return menuItem;
}
public boolean hasNext(){
/*检查是否已经取得数组内所有的元素,如果还有元素待遍历则返回true;
由于使用的是固定长度的数组,所以不但要检查是否超出了数组长度,也必须检查是否下一项是null,如果是null,就没有其他项了
*/
if(position>=items.length||items[position]==null){
return false;
}else{
return true;
}
}
}
//实现迭代器接口 PancakeHouseMenu
public class PancakeHouseMenuIterator implements Iterator{
ArrayList items;
int position = 0; //position记录当前数组遍历的位置
public PancakeHouseMenuIterator(ArrayList items){ //构造器需要被传入一个菜单项的数组当作参数
this.items=items;
}
public Object next(){ //返回数组内的下一项,并递增其位置
MenuItem menuItem= items.get(position);
position=position+1;
return menuItem;
}
public boolean hasNext(){
if(position>=items.size()||items.get(position)==null){
return false;
}else{
return true;
}
}
}
public class DinerMenu{
static final int MAX_ITEMS=6;
int numberOfItems=0;
MenuItem[] menuItems;
public DinerMenu(){
menuItems=new MenuItem[MAX_ITEMS];
addItem("Vegetarian BLT","1111111111111",true,2.99);
addItem("BLT","222222222222",false,2.99);
addItem("Soup of the day","2222222222222",false,3.29);
addItem("Hotdog","33333333333333",false,3.05);
//继续加入其他项
}
public void addItem(String name,String description,boolean vegetarian,double price){
MenuItem menuItem= new MenuItem(name,description,vegetarian,price);
if(numberOfItems>=MAX_ITEMS){
System.err.println("Sorry,menu is full! Can't add item to menu");
}else{
menuItems[numberOfItems]=menuItem;
numberOfItems=numberOfItems+1;
}
}
//返回迭代器接口。客户不需要知道餐厅菜单是如何维护菜单项的,也不需要知道迭代器是如何实现的,客户只需要直接使用这个迭代器遍历菜单项即可。
public Iteraor createIterator(){
return new DinerMenuIterator(menuItems);
}
//菜单的其他方法。。。。
}
public class PancakeHouseMenu{
ArrayList menuItems;
public PancakeHouseMenu(){
menuItems=new ArrayList();
addItem("K&B's Pancake Breakfast","1111111111111",true,2.99);
addItem("Regular Pancake Breakfast","222222222222",false,2.99);
addItem("Blueberry Pancakes","2222222222222",true,3.29);
addItem("Waffles","33333333333333",true,3.05);
}
public void addItem(String name,String description,boolean vegetarian,double price){
MenuItem menuItem= new MenuItem(name,description,vegetarian,price);
menuItems.add(menuItem);
}
public Iteraor createIterator(){
return new PancakeHouseMenuIterator(menuItems);
}
//其他方法
}
public class Waitress{
PancakeHouseMenu pancakeHouseMenu;
DinerMenu dinerMenu;
//在构造器中,女招待照顾两个菜单
public Waitress(PancakeHouseMenu pancakeHouseMenu,DinerMenu dinerMenu){
this.pancakeHouseMenu=pancakeHouseMenu;
this.dinerMenu=dinerMenu;
}
public void printMenu(){
Iterator pancakeIterator=pancakeHouseMenu.createIterator();
Iterator dinerIterator=dinerMenu.createIterator();
System.out.println("Menu\n-------------\nBREAKFAST");
printMenu(pancakeIterator);
System.out.println("\nLUNCH");
printMenu(dinerIterator);
}
private void printMenu(Iterator iterator){ //重载printMenu方法,使用迭代器遍历菜单项并打印
while(iterator.hasNext()){
MenuItem menuItem=(MenuItem)iterator.next();
System.out.print(menuItem.getName()+",");
System.out.print(menuItem.getPrice()+"--");
System.out.println(menuItem.getDescription());
}
}
//其他方法
}
public class MenuTestDriver{
public static void main(String args[]){
PancakeHouseMenu pancakeHouseMenu=new PancakeHouseMenu();
DinerMenu dinerMenu= new DinerMenu();
Waitress waitress=new Waitress(pancakeHouseMenu,dinerMenu);
waitress.printMenu();
}
}类图
进一步改进:为两份菜单设立共同的接口。
设计原则
一个类应该只有一个引起变化的原因。
类的每个责任都有改变的潜在区域。超过一个责任则意味着多个改变的区域。该原则说明了应该尽量让每个类保持单一责任。
组合模式
允许将对象组合成树形结构来表现“整体/部分”层次结构。组合能够让客户以抑制的方式处理个别对象以及对象组合。
组合模式让我们 能用树形方式创建对象的结构,树里面包含了组合以及个别的对象。使用组合结构,我们能把相同的操作应用在组合和个别对象上。即:在大多数情况下,我们可以忽略对象组合和个别对象的差别。
区别各类模式:
策略模式:封装可互换的行为,并使用委托决定使用哪一个。
适配器模式:改变一个或多个类的接口。
迭代器模式:提供一个方式来遍历集合,而无需暴露集合的实现。
外观模式:简化一群类的接口。
组合模式:客户可以将对象的集合以及个别的对象一视同仁。
观察者模式:当某个状态改变是,允许一群对象能被通知到。
要点:
(1)迭代器允许访问聚合的元素,而不需暴露他的内部结构。
(2)迭代器将遍历聚合的工作封装进一个对象中。
(3)当使用迭代器的时候,我们依赖聚合提供遍历。
(4)迭代器提供一个通用的接口,让我们遍历聚合的项,当我们编码使用聚合的项时,就可以使用多态机制。
(5)我们应该努力让一个类只分配一个责任。
(6)组合模式提供一个结构,可同时包容个别对象和组合对象。
(7)组合模式允许客户对个别对象和组合对象一视同仁。
(8)组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点。
(9)在实现组合模式时,有许多设计上的折中。要根据需要平衡透明性和安全性。
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
迭代器模式让我们能够游走于聚合内的每个元素,而又不暴露其内部的表示。把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。
集合collection/聚合aggregate:指一群对象,其存储方法可以是各式各样的数据结构,例如:列表、数组、散列表,无论用什么方式存储,一律可以视为是集合/聚合。
实例:
public class MenuItem{
String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name,String description,boolean vegetarian,double price){
this.name=name;
this.description=description;
this.vegetarian=vegetarian;
this.price=price;
}
public String getName(){ return name;}
public String getDescription(){ return description;}
public double getprice(){ return price;}
public boolean isVegetarian(){ return vegetarian;}
}
public interface Iterator{
boolean hasNext(); //返回一个布尔值,判断是否还有更多的元素
Object next(); //返回下一个元素
}
//实现迭代器接口 DinerMenu
public class DinerMenuIterator implements Iterator{
MenuItem[] items;
int position = 0; //position记录当前数组遍历的位置
public DinerMenuIterator(MenuItem[] items){ //构造器需要被传入一个菜单项的数组当作参数
this.items=items;
}
public Object next(){ //返回数组内的下一项,并递增其位置
MenuItem menuItem= items[position];
position=position+1;
return menuItem;
}
public boolean hasNext(){
/*检查是否已经取得数组内所有的元素,如果还有元素待遍历则返回true;
由于使用的是固定长度的数组,所以不但要检查是否超出了数组长度,也必须检查是否下一项是null,如果是null,就没有其他项了
*/
if(position>=items.length||items[position]==null){
return false;
}else{
return true;
}
}
}
//实现迭代器接口 PancakeHouseMenu
public class PancakeHouseMenuIterator implements Iterator{
ArrayList items;
int position = 0; //position记录当前数组遍历的位置
public PancakeHouseMenuIterator(ArrayList items){ //构造器需要被传入一个菜单项的数组当作参数
this.items=items;
}
public Object next(){ //返回数组内的下一项,并递增其位置
MenuItem menuItem= items.get(position);
position=position+1;
return menuItem;
}
public boolean hasNext(){
if(position>=items.size()||items.get(position)==null){
return false;
}else{
return true;
}
}
}
public class DinerMenu{
static final int MAX_ITEMS=6;
int numberOfItems=0;
MenuItem[] menuItems;
public DinerMenu(){
menuItems=new MenuItem[MAX_ITEMS];
addItem("Vegetarian BLT","1111111111111",true,2.99);
addItem("BLT","222222222222",false,2.99);
addItem("Soup of the day","2222222222222",false,3.29);
addItem("Hotdog","33333333333333",false,3.05);
//继续加入其他项
}
public void addItem(String name,String description,boolean vegetarian,double price){
MenuItem menuItem= new MenuItem(name,description,vegetarian,price);
if(numberOfItems>=MAX_ITEMS){
System.err.println("Sorry,menu is full! Can't add item to menu");
}else{
menuItems[numberOfItems]=menuItem;
numberOfItems=numberOfItems+1;
}
}
//返回迭代器接口。客户不需要知道餐厅菜单是如何维护菜单项的,也不需要知道迭代器是如何实现的,客户只需要直接使用这个迭代器遍历菜单项即可。
public Iteraor createIterator(){
return new DinerMenuIterator(menuItems);
}
//菜单的其他方法。。。。
}
public class PancakeHouseMenu{
ArrayList menuItems;
public PancakeHouseMenu(){
menuItems=new ArrayList();
addItem("K&B's Pancake Breakfast","1111111111111",true,2.99);
addItem("Regular Pancake Breakfast","222222222222",false,2.99);
addItem("Blueberry Pancakes","2222222222222",true,3.29);
addItem("Waffles","33333333333333",true,3.05);
}
public void addItem(String name,String description,boolean vegetarian,double price){
MenuItem menuItem= new MenuItem(name,description,vegetarian,price);
menuItems.add(menuItem);
}
public Iteraor createIterator(){
return new PancakeHouseMenuIterator(menuItems);
}
//其他方法
}
public class Waitress{
PancakeHouseMenu pancakeHouseMenu;
DinerMenu dinerMenu;
//在构造器中,女招待照顾两个菜单
public Waitress(PancakeHouseMenu pancakeHouseMenu,DinerMenu dinerMenu){
this.pancakeHouseMenu=pancakeHouseMenu;
this.dinerMenu=dinerMenu;
}
public void printMenu(){
Iterator pancakeIterator=pancakeHouseMenu.createIterator();
Iterator dinerIterator=dinerMenu.createIterator();
System.out.println("Menu\n-------------\nBREAKFAST");
printMenu(pancakeIterator);
System.out.println("\nLUNCH");
printMenu(dinerIterator);
}
private void printMenu(Iterator iterator){ //重载printMenu方法,使用迭代器遍历菜单项并打印
while(iterator.hasNext()){
MenuItem menuItem=(MenuItem)iterator.next();
System.out.print(menuItem.getName()+",");
System.out.print(menuItem.getPrice()+"--");
System.out.println(menuItem.getDescription());
}
}
//其他方法
}
public class MenuTestDriver{
public static void main(String args[]){
PancakeHouseMenu pancakeHouseMenu=new PancakeHouseMenu();
DinerMenu dinerMenu= new DinerMenu();
Waitress waitress=new Waitress(pancakeHouseMenu,dinerMenu);
waitress.printMenu();
}
}类图
进一步改进:为两份菜单设立共同的接口。
设计原则
一个类应该只有一个引起变化的原因。
类的每个责任都有改变的潜在区域。超过一个责任则意味着多个改变的区域。该原则说明了应该尽量让每个类保持单一责任。
组合模式
允许将对象组合成树形结构来表现“整体/部分”层次结构。组合能够让客户以抑制的方式处理个别对象以及对象组合。
组合模式让我们 能用树形方式创建对象的结构,树里面包含了组合以及个别的对象。使用组合结构,我们能把相同的操作应用在组合和个别对象上。即:在大多数情况下,我们可以忽略对象组合和个别对象的差别。
区别各类模式:
策略模式:封装可互换的行为,并使用委托决定使用哪一个。
适配器模式:改变一个或多个类的接口。
迭代器模式:提供一个方式来遍历集合,而无需暴露集合的实现。
外观模式:简化一群类的接口。
组合模式:客户可以将对象的集合以及个别的对象一视同仁。
观察者模式:当某个状态改变是,允许一群对象能被通知到。
要点:
(1)迭代器允许访问聚合的元素,而不需暴露他的内部结构。
(2)迭代器将遍历聚合的工作封装进一个对象中。
(3)当使用迭代器的时候,我们依赖聚合提供遍历。
(4)迭代器提供一个通用的接口,让我们遍历聚合的项,当我们编码使用聚合的项时,就可以使用多态机制。
(5)我们应该努力让一个类只分配一个责任。
(6)组合模式提供一个结构,可同时包容个别对象和组合对象。
(7)组合模式允许客户对个别对象和组合对象一视同仁。
(8)组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点。
(9)在实现组合模式时,有许多设计上的折中。要根据需要平衡透明性和安全性。
相关文章推荐
- HDOJ 2066 一个人的旅行 (最短路 Dijkstra && SPFA)
- 黑马程序员——JAVA基础——IO流
- Chisel Tutorial(六)——端口
- ionic中隐藏header
- POJ 3468-A Simple Problem with Integers(线段树)
- jquery.seat-charts选座
- cmd if语句
- csdn博客积分规则
- 转载C#中Trim()、TrimStart()、TrimEnd()的用法
- 关于Android中的四大组件(Service的开启与关闭)
- java.util.NoSuchElementException: No mapping for class sun.awt.AppContext
- 网络编程学习之TCP客户端与服务器端
- 怎么将PDF文件转换成HTML格式
- cmd查看端口号以及该端口号对应进程并停止进程
- 剑指offer_面试题25_二叉树中和为某一值的路径
- MetaSploit framework基础知识
- IOS下移除按钮默认美化样式
- 在一个JSP页面中包含另一个JSP页面的三种方式
- C++编写网页控件,遇到的问题总结
- win10 亮度不能调节的解决办法(亲测办法,安装两台win10两台都是这样解决)