设计模式之访问者模式+组合模式



访问者模式Visitor


CRM 客户关系管理


类型:企业客户,个人客户
功能:提出服务申请、客户偏好分析、客户价值分析


定义:
表示一个作用于某对象结构中的各元素的操作。
它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作




Visitor:
访问者接口,为所有的访问者对象声明一个visit方法,
用来代表为对象添加的功能,理论上可以代表任意的功能
ConcreteVisitor:
具体的访问者实现,实现要真正被添加到对象结构中的功能
Element:
抽象的元素对象
ConcreteElement:具体的元素对象


ObjectStructure:对象结构,通常包含多个被访问的对象




两次分发(调用通路)-动态添加功能的关键


到底添加什么功能,取决于两点:
1.访问者的类型
2.元素的类型


前提条件:对象结构比较稳定(客户类型基本不会变了)


结合组合模式一起使用
Composite 组合节点
Leaf 叶子节点


打印结构的功能PrintNameVisitor(示意)


优点
1.更好的扩展性
2.分离无关的行为(单一职责原则SCP)
3.更好的复用性


缺点
破坏封装




场景:对象结构比较稳定,但是又需要经常给结对结构添加新的功能


XUtils 注解(运行时注解)
ButterKnife 注解框架(编译期注解) jack wharton


@ViewInject(R.id.btn) Button btn;
btn = findViewById(R.id.btn);


Mirror API 模块  APT


修改类(访问类)
类的结构是固定的


代码实现如下:


受访者接口类:

/**
 * 抽象的组件对象(相当于访问者模式中的Element) 
 * @date 2016年2月29日 
 */
public abstract class Component {

	/**
	 * 接受访问
	 * @param visitor
	 */
	public abstract void accept(Visitor visitor);
	
	
	/**
	 * 添加子节点
	 * @param child
	 */
	public void addChild(Component child){
		throw new UnsupportedOperationException("对象不支持这个功能!");
	}
	
	/**
	 * 移除子节点
	 * @param child
	 */
	public void removeChild(Component child){
		throw new UnsupportedOperationException("对象不支持这个功能!");
	}
	
	/**
	 * 获取指定索引位置的子节点
	 * @param index
	 * @return
	 */
	public Component getChildren(int index){
		throw new UnsupportedOperationException("对象不支持这个功能!");
	}
}

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

/**
 * 组合节点(相当于ConcreteElement) 
 * @date 2016年2月29日 
 */
public class Composite extends Component {

	// 名字
	private String name;
	// 子节点的集合
	private List<Component> childComponents = new ArrayList<Component>();

	public Composite(String name) {
		super();
		this.name = name;
	}
	

	@Override
	public void accept(Visitor visitor) {
		visitor.visitComposite(this);
		//循环子元素,让子元素也接受访问(子节点也要打印出来)
		for (Component c : childComponents) {
			c.accept(visitor);
		}
	}

	@Override
	public void addChild(Component child) {
		childComponents.add(child);
	}

	@Override
	public void removeChild(Component child) {
		childComponents.remove(child);
	}

	@Override
	public Component getChildren(int index) {
		return childComponents.get(index);
	}
	
	public String getName() {
		return name;
	}

}

/**
 * 叶子节点(相当于ConcreteElement) 
 * @date 2016年2月29日 
 */
public class Leaf extends Component {

	private String name;

	public Leaf(String name) {
		super();
		this.name = name;
	}

	@Override
	public void accept(Visitor visitor) {
		visitor.visitLeaf(this);
	}
	
	public String getName() {
		return name;
	}

}

访问者相关接口类:

/**
 * 访问者接口 
 * @date 2016年2月29日 
 */
public interface Visitor {

	/**
	 * 访问组合对象
	 * @param composite
	 */
	void visitComposite(Composite composite);
	
	/**
	 * 访问叶子对象
	 * @param leaf
	 */
	void visitLeaf(Leaf leaf);
	
}

/**
 * 打印节点名称接口 
 * @date 2016年2月29日 
 */
public class PrintNameVisitor implements Visitor {

	@Override
	public void visitComposite(Composite composite) {
		System.out.println("打印  组合:"+composite.getName());
	}

	@Override
	public void visitLeaf(Leaf leaf) {
		System.out.println("打印  叶子:"+leaf.getName());
	}

}
/**
 * 记录节点名称访问接口
 * @author lenovo 
 */
public class RecordNameVisitor implements Visitor {

	@Override
	public void visitComposite(Composite composite) {
		System.out.println("记录   组合:"+composite.getName());
	}

	@Override
	public void visitLeaf(Leaf leaf) {
		System.out.println("记录  叶子:"+leaf.getName());
	}

}


辅助类:

/**
 * 对象结构 
 * @date 2016年2月29日 
 */
public class ObjectStructure {

	//对象结构
	private Component root;
	
	/**
	 * 添加功能
	 * @param visitor
	 */
	public void handleRequest(Visitor visitor){
		if(root != null){
			root.accept(visitor);
		}
	}
	
	public void setRoot(Component root) {
		this.root = root;
	}
}


调用示例:

public class Client {

	public static void main(String[] args) {
		//创建一个树状结构
		Component root = new Composite("服装");
		
		Component c1 = new Composite("男装");
		Component c2 = new Composite("女装");
		root.addChild(c1);
		root.addChild(c2);
		
		Component lf1 = new Leaf("衬衣");
		Component lf2 = new Leaf("夹克");
		c1.addChild(lf1);
		c1.addChild(lf2);
		
		Component lf3 = new Leaf("裙子");
		Component lf4 = new Leaf("包臀裙");
		c2.addChild(lf3);
		c2.addChild(lf4);
		
		//动态添加功能
		ObjectStructure os = new ObjectStructure();
		os.setRoot(root);
		os.handleRequest(new PrintNameVisitor());
		System.out.println("++++++++++++++++++++++++");
		os.handleRequest(new RecordNameVisitor());
		
	}

}

运行结果:

打印  组合:服装
打印  组合:男装
打印  叶子:衬衣
打印  叶子:夹克
打印  组合:女装
打印  叶子:裙子
打印  叶子:包臀裙
++++++++++++++++++++++++
记录   组合:服装
记录   组合:男装
记录  叶子:衬衣
记录  叶子:夹克
记录   组合:女装
记录  叶子:裙子
记录  叶子:包臀裙


整理自教程



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值