您的位置:首页 > 其它

初学设计模式(7)迭代模式和组合模式

2013-03-05 13:53 141 查看
家里蹲了将近一个多月,终于找到一份新的工作,开始了另一端修行。

这段时间里,通读了大半head first设计模式,如今已经看到了代理模式。看着自己知识的日积月累,心里也是各种欢喜,坚定了要一读到底的决心。(虽然实用与否依然需要项目的磨练)

今天将之前没写的几个模式补上。首先来讲讲,跌到模式和组合模式。

心法(8):迭代模式。

说起这个迭代模式,其实跟我们平时用到的for循环很类似,应该说,是把for循环给抽象化,忽略实际的遍历过程,在client code端直接通过moveNext和hasNext来实现遍历整个数据结构。这里说是数据结构,其实在代码中就是表现成类实例的结构。

心法(9):组合模式。

当我们需要把几个相关的类组合成一个树状结构时,便可以通过组合模式,将那些类的实例,通过统一的接口进行组织,

由于组合模式从某种程度上依赖于迭代模式的实现,因此,我将两者代码合并在一起。

以下是代码:

Component(这就是需要组织成树状结构的类)

虚基类,用于concrete class继承,其中每个方法都定义一个默认的实现----抛出一个不支持的实现

public abstract class MenuComponent {
public String getDescription(){
throw new UnsupportedOperationException();
}
public String getName(){
throw new UnsupportedOperationException();
}

public void add(MenuComponent mc){
throw new UnsupportedOperationException();
}

public void remove(MenuComponent mc){
throw new UnsupportedOperationException();
}

public MenuComponent getChild(int index){
throw new UnsupportedOperationException();
}

public Iterator<MenuComponent> createIterator(){
throw new UnsupportedOperationException();
}
}


两个concrete class

Menu,compose了一个MenuComponent的集合,说明menu可以充当一个容器。

public class Menu extends MenuComponent{
ArrayList<MenuComponent> items=new ArrayList<>();
String description;
String name;

public Menu(String des,String name){
this.description=des;
this.name=name;
}
public String getDescription(){
return this.description;
}
public String getName(){
return this.name;
}

public void add(MenuComponent mc){
items.add(mc);
}

public void remove(MenuComponent mc){
if(items.contains(mc)){
items.remove(mc);
}
}

public MenuComponent getChild(int index){
return items.get(index);
}

public Iterator<MenuComponent> createIterator(){
return new CompositeIterator(items.iterator());
}
}


MenuItem:这只是一个MenuComponent最基础的单元,可以作为menu的子项。

public class MenuItem extends MenuComponent {
String name;
String description;

public MenuItem(String name,String des){
this.name=name;
this.description=des;
}

public String getDescription(){
return this.description;
}
public String getName(){
return this.name;
}

public Iterator<MenuComponent> createIterator(){
return new NullIterator();
}
}


Iterator:

CompositeIterator:用于遍历树状结构的实例集合

public class CompositeIterator implements Iterator<MenuComponent> {

Stack<Iterator<MenuComponent>> itemStack=new Stack<>();

public CompositeIterator(Iterator<MenuComponent> iterator) {
// TODO Auto-generated constructor stub
itemStack.add(iterator);
}

@Override
public boolean hasNext() {
// TODO Auto-generated method stub
if(itemStack.size()==0){
return false;
}else{
Iterator<MenuComponent> iter=itemStack.peek();
if(!iter.hasNext()){
itemStack.pop();
return hasNext();
}else{
return true;
}
}
}

@Override
public MenuComponent next() {
// TODO Auto-generated method stub
if(hasNext()){
Iterator<MenuComponent> iter=itemStack.peek();
MenuComponent mc=iter.next();
if(mc instanceof Menu){
itemStack.add(mc.createIterator());
}
return mc;
}else{
return null;
}
}

@Override
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperation();
}

}


NullIterator:由于MenuItem是最基础的子项,因此对他迭代是无意义的,因此创建此类,并相应的返回false和null。

public class NullIterator implements Iterator<MenuComponent> {

@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return false;
}

@Override
public MenuComponent next() {
// TODO Auto-generated method stub
return null;
}

@Override
public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}

}


Waitress:用于遍历整个对象集合的client code。

public class Waitress {
MenuComponent menus;

public Waitress(MenuComponent mc){
this.menus=mc;
}

public void printAll(){
Iterator<MenuComponent> iter=menus.createIterator();
while(iter.hasNext()){
MenuComponent mc=iter.next();
System.out.println(mc.getName()+" "+mc.getDescription());
}
}
}


Main函数:

public static void main(String[] args) {
// TODO Auto-generated method stub
Menu m1 = new Menu("aaa", "a");
Menu m2 = new Menu("bbb", "b");
Menu m3 = new Menu("ccc", "c");

Menu all=new Menu("all", "all");
all.add(m1);
m1.add(m2);
m2.add(m3);
m3.add(new MenuItem("item", "item"));

Waitress w=new Waitress(all);
w.printAll();
}




如图中所示,这就是我们创建的menu结构图,当我们需要对这个整个结构进行遍历的时候,就需要用到composite iterator类。使用递归的实现,进行遍历。

(PS:但是这里的递归实现是有问题的,当运行main函数的时候,会发现item被显示了5次,ccc被显示了2次,而我们的本意则是每个子项只显示一次。因此这里一的算法肯定错了,我已经在论坛里面挂了贴----------(请猛戳这里!!
) 希望能得到大牛前辈们的指点,算法确实基础不是很好,决定设计模式结束之后开始重新复习数据结构和算法)

这里贴下结构截图,结果显示不是正确,但至少这个模式是对的。

a aaa
b bbb
c ccc
item item
item item
c ccc
item item
item item
item item


这里要提一个设计模式,就是A class should have only one reason to change. 其实也就是one class,one responsibility。 对于以上的设计,每个menu除了负责本身menu的getter和setter之外就是createIterator方法,这个方法本就是menu的职责之内,而menu并不负责对整个树状结构的遍历,其实现是交给了composite
iterator,即composite iterator仅仅只是用来遍历树状结构的对象集,但他并不知道他处理的是menu还是menuitem,只是一个menucomponent。(depend on abstraction,not concrete class)

对于组合模式和迭代模式的学习就暂且到这。今后将利用项目中的实际操作经验,来完善对这两个模式的理解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式