论坛首页 Java企业应用论坛

关于23种设计模式的有趣见解 --- VISITOR

浏览 4731 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-01-27  
好久没发贴了。现在大家都在讨论设计模式,今天也来火一把:)
就把http://www.jdon.com上看到的有个《关于23种设计模式的有趣见解》解答一下,请大家拍砖。
先从VISITOR开始吧:

VISITOR—情人节到了,要给每个MM送一束鲜花和一张卡片,可是每个MM送的花都要针对她个人的特点,每张卡片也要根据个人的特点来挑,我一个人哪搞得清楚,还是找花店老板和礼品店老板做一下Visitor,让花店老板根据MM的特点选一束花,让礼品店老板也根据每个人特点选一张卡,这样就轻松多了;
       
访问者模式:访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。

先上代码:
先实现美女类,用四大美女来模拟。
package com.test.girl;

public interface Girl {
	void flow();
	void card();
}

package com.test.girl;

public class XiShi implements Girl {

	@Override
	public void card() {
		System.out.println("credit card");
	}

	@Override
	public void flow() {
		System.out.println("rose");
	}
}

package com.test.girl;

public class DiaoChan implements Girl {

	@Override
	public void card() {
		System.out.println("shop card");
	}

	@Override
	public void flow() {
		System.out.println("peony");
	}

}

package com.test.girl;

public class WangZhaojun implements Girl {

	@Override
	public void card() {
		System.out.println("king card");
	}

	@Override
	public void flow() {
		System.out.println("orchid");
	}
}

package com.test.girl;

public class YangYuhuan implements Girl {

	@Override
	public void card() {
		System.out.println("vip card");
	}

	@Override
	public void flow() {
		System.out.println("plum blossom");
	}
}

下面定义观察者:
package com.test.visitor;

public interface Visitor {
	void visit();
	void add(Object obj);
	void remove(Object obj);
}

这里只实现花店:
package com.test.visitor;

import java.util.ArrayList;
import java.util.List;

import com.test.girl.Girl;

public class Flowor implements Visitor {

	private List<Girl> girls = new ArrayList<Girl>();
	
	@Override
	public void visit() {
		for(Girl g:girls){
			g.flow();
		}
	}
	@Override
	public void add(Object g){
		girls.add((Girl)g);
	}
	@Override
	public void remove(Object g){
		girls.remove((Girl)g);
	}
}

写测试类:
package com.test.visitor;

import com.test.girl.DiaoChan;
import com.test.girl.Girl;
import com.test.girl.WangZhaojun;
import com.test.girl.XiShi;
import com.test.girl.YangYuhuan;

public class VisitorTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Visitor v = new Flowor();
		Girl 西施 = new XiShi();
		Girl 貂蝉 = new DiaoChan();
		Girl 王昭君 = new WangZhaojun();
		Girl 杨玉环 = new YangYuhuan();
		v.add(西施);
		v.add(貂蝉);
		v.add(王昭君);
		v.add(杨玉环);
		
		v.visit();
		System.out.println("+++++++++++");
		v.remove(杨玉环);
		v.visit();
	}
}
   发表时间:2010-01-29  
从代码没看出Vistor 的真谛
0 请登录后投票
   发表时间:2010-01-29  
有点适配器的味道。
0 请登录后投票
   发表时间:2010-01-30  
这明显不是visitor...偏差太大了……你的visitor居然和你要访问的东西是聚合关系。
0 请登录后投票
   发表时间:2010-02-02  

这个模式凭着感觉写出来的,这个应该是观察者模式。写错了。
修正一下。
1.类图:(摘自:http://zh.wikipedia.org/wiki/%E8%AE%BF%E9%97%AE%E8%80%85%E6%A8%A1%E5%BC%8F
visitor

 

2.DEMO:

 

元素角色:定义一个accept操作,它以一个访问者为参数。

package com.test.girl;

import com.test.visitor.Visitor;

public interface Girl {
	void accept(Visitor visitor);
	void flower();
	void card();
}

 下面是具体的元素角色:

package com.test.girl;

import com.test.visitor.Visitor;


public class DiaoChan implements Girl {

	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}

	/**
	 * 腊梅
	 */
	@Override
	public void flower() {
		System.out.println("winter sweet");
	}

	@Override
	public void card() {
		System.out.println("shopping card");
	}

}

 

package com.test.girl;

import com.test.visitor.Visitor;

public class WangZhaojun implements Girl {

	@Override
	public void card() {
		System.out.println("king card");
	}

	@Override
	public void flower() {
		System.out.println("orchid");
	}


	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}
}

 

package com.test.girl;

import com.test.visitor.Visitor;

public class XiShi implements Girl {

	@Override
	public void card() {
		System.out.println("credit card");
	}

	@Override
	public void flower() {
		System.out.println("rose");
	}

	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}
}

 

package com.test.girl;

import com.test.visitor.Visitor;


public class YangYuhuan implements Girl {

	@Override
	public void card() {
		System.out.println("vip card");
	}

	@Override
	public void flower() {
		System.out.println("plum blossom");
	}

	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}
}

 访问者角色(Visitor):为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。

package com.test.visitor;

import com.test.girl.DiaoChan;
import com.test.girl.WangZhaojun;
import com.test.girl.XiShi;
import com.test.girl.YangYuhuan;

public interface Visitor {
	void visit(DiaoChan diaoChan);
	void visit(WangZhaojun wangZhaojun);
	void visit(XiShi xiShi);
	void visit(YangYuhuan yangYuhuan);
}

 

下面是具体访问者:

package com.test.visitor;

import com.test.girl.DiaoChan;
import com.test.girl.WangZhaojun;
import com.test.girl.XiShi;
import com.test.girl.YangYuhuan;

/**
 * record every girl's flower.
 * @author Dave Li
 *
 */
public class FlowerBoss implements Visitor {

	@Override
	public void visit(DiaoChan diaoChan) {
		diaoChan.flower();
	}

	@Override
	public void visit(WangZhaojun wangZhaojun) {
		wangZhaojun.flower();
	}

	@Override
	public void visit(XiShi xiShi) {
		xiShi.flower();
	}

	@Override
	public void visit(YangYuhuan yangYuhuan) {
		yangYuhuan.flower();
	}

}

 对象结构角色(Object Structure):这是使用访问者模式必备的角色。它要具备以下特征:

      1)能枚举它的元素;

      2)可以提供一个高层的接口以允许该访问者访问它的元素;

      3)可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合。

package com.test.visitor;

import com.test.girl.DiaoChan;
import com.test.girl.Girl;
import com.test.girl.WangZhaojun;
import com.test.girl.XiShi;
import com.test.girl.YangYuhuan;
/*
 * 采购鲜花
 */
public class FlowerPurchase {

	private Girl[] girls = {new DiaoChan(),
							new WangZhaojun(),
							new XiShi(),
							new YangYuhuan()};
	
	public void purchase(Visitor v){
		for(Girl girl:girls){
			girl.accept(v);
		}
	}
}

 

测试类:

package com.test.visitor;

public class Test {
	public static void main(String[] args) {
		FlowerPurchase purchase = new FlowerPurchase();
		purchase.purchase(new FlowerBoss());
	}
}

 

3.特点:

双重分配:

             purchase.purchase(new FlowerBoss());(给每个具体的角色分派一个具体观察者)。

             visitor.visit(this);具体访问者模式再根据参数的不同来选择方法来执行。

 

在两个接口Visitor和Girl中,确保Girl很少变化,也就是说,确保不能老有新的Element元素类型加进来,可以变化的是访问者行为或操作,也就是Visitor的不同子类可以有多种,这样使用访问者模式最方便.

所以这个例子不太合适,花店的顾客是不断变化的,girl也是不断变化的。

 

4,适用场合:

《设计模式》一书中给出了访问者模式适用的情况:

  1) 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。

  2) 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中。

  3) 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。

  4) 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

0 请登录后投票
   发表时间:2010-02-09  
前面观察者模式写的有点问题
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics