家里蹲了将近一个多月,终于找到一份新的工作,开始了另一端修行。
这段时间里,通读了大半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)
对于组合模式和迭代模式的学习就暂且到这。今后将利用项目中的实际操作经验,来完善对这两个模式的理解。