设计模式-责任链模式

废话不多说,直接上文。
责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
为了有助于理解,我们还是用烂大街的例子,请假。
在学校,你作为食物链最底层(ps:这里有人会说我是xx委员什么的,你这就属于杠精了额),请假情况一般是这样的:先向班长请假,如果班长没权处理就会向老师请,逐级递增,一直到导员,于是,我们角色定义就成了如下:
1.班长(Monitor):可以请假不开会
2.老师(Teacher):可以请假不上课
3.导师(Supervisor):可以请假不上学

附代码:

处理请求的抽象类,具体执行由子类完成
public abstract class Handler
{
    /**
     * 执行人
     */
    protected Handler successor;
    /**
     * 执行人名称
     */
    protected String name;

    /**
     * 处理请求,由子类完成
     * @param request
     */
    public abstract void handleRequest(String request);

    /**
     * 设置下一个处理请求的人
     * @param successor
     */
    public void setNextHander(Handler successor)
    {
        this.successor = successor;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

}
班长执行请求(班长具有的属性方法:名称、执行方法、执行人(下家)、设置下家)
public class Monitor extends Handler
{
    public Monitor(String name)
    {
        this.name = name;
    }

    /**
     * 执行自己有权的请求,无权则给下一个执行
     */
    @Override
    public void handleRequest(String request)
    {
        if ("请假不开会".equals(request))
        {
            System.out.println(name + "可以处理" + request + ",给予批准!");
        }
        else
        {
            System.out.println(name + "不可以处理" + request + "转交给" + successor.getName());
            successor.handleRequest(request);
        }
    }

}

其他角色代码同班长

public class ExecuteChain
{
    public static void main(String[] args)
    {
        Handler teacher = new Teacher("老师");
        Handler monitor = new Monitor("班长");
        Handler supervisor = new Supervisor("导员");
        monitor.setNextHander(teacher);
        teacher.setNextHander(supervisor);
        monitor.handleRequest("请假不上学");
    }

}

执行链

工作中应用的例子:
刚毕业那会儿工作有这样一个场景就用了责任链模式,首先我们有一个存着特定数据的excel,现在需要把它解析成我们需要的数据,最终的方案是通过正则和配置文件来匹配,没有匹配就通过搜索引擎lucene查询分词(事先定义好自己的分词),如果还没有匹配到就通过drools规则引擎匹配,其中任何一个通过匹配就结束。

定义如下:

第一层识别:

public class LibraryMaterialMatcher extends ComparableMatcher
{
   public LibraryMaterialMatcher()
   {
      this.priority = 1;
   }

   @Override
   public void doMatchInternal(MaterialMatchContext materialContext, MatchChain matchChain) throws MtrlMatchException
   {
    ...
  
    // 继续链条处理
    matchChain.doMatch(materialContext);
  }
}

  第二层识别:

public class LuceneMaterialMatcher extends ComparableMatcher
{
   public LuceneMaterialMatcher()
   {
      this.priority = 5;
   }

   @Override
   public void doMatchInternal(MaterialMatchContext materialContext, MatchChain matchChain) throws MtrlMatchException
   {
    ...
  
    // 继续链条处理
    matchChain.doMatch(materialContext);
  }
}

  第三层识别:

public class DroolsMaterialMatcher extends ComparableMatcher
{
   public DroolsMaterialMatcher()
   {
      this.priority = 10;
   }

   @Override
   public void doMatchInternal(MaterialMatchContext materialContext, MatchChain matchChain) throws MtrlMatchException
   {
    ...
  
    // 继续链条处理
    matchChain.doMatch(materialContext);
  }
}

  其中父类和接口定义如下:

//物料匹配器
public interface MtrlMatcher extends Comparable<Object>
{
    public void doMatch(MaterialMatchContext materialContext, MatchChain matchChain) throws MtrlMatchException;
}
//有序匹配
public abstract class ComparableMatcher implements MtrlMatcher
{
	/**
	 * 匹配器的优先级
	 */
	protected int priority = -1;

	/**
	 * Matcher 排序
	 */
	public int compareTo(Object obj)
	{
		ComparableMatcher otherMatcher = (ComparableMatcher) obj;
		int priorityDifference = this.priority - otherMatcher.priority;
		return priorityDifference;
	}

	@Override
	public void doMatch(MaterialMatchContext materialContext, MatchChain matchChain) throws MtrlMatchException
	{
		if (this.getPriority() <= materialContext.getPrioritySkip())
		{
			matchChain.doMatch(materialContext);
		}
		else
		{
			doMatchInternal(materialContext, matchChain);
		}
	}

	/**
	 * @Description: 子类匹配器具体实现
	 */
	public abstract void doMatchInternal(MaterialMatchContext materialContext, MatchChain matchChain) throws MtrlMatchException;
	
	
	public int getPriority()
	{
		return priority;
	}

	public void setPriority(int priority)
	{
		this.priority = priority;
	}

}

  以上是匹配器的定义,接下来介绍具体调用

//调用匹配链
//由MatchChainFactory创建MatchChain的实现,
MatchChain matchChain = MatchChainFactory.createMatchChain();//这时匹配器已经存在
//设置参数
MaterialMatchContext materialMatchContext = new MaterialMatchContext();
materialMatchContext.setMaterialProject(materialProject);
materialMatchContext.setUserMaterial(userMaterial);
matchChain.doMatch(materialMatchContext);
matchChain.reset();

  

public interface MatchChain
{
    //匹配方法
    public void doMatch(MaterialMatchContext materialContext) throws MtrlMatchException;

    /**
     * @Description: 重置过滤器
     * @return void
     */
    public void reset();
}
public class MatchChainImpl implements MatchChain
{
    private static final Logger logger = LoggerFactory.getLogger(MatchChainImpl.class);

    private List<MtrlMatcher> matchers;

    private int index = 0;

    public MatchChainImpl(List<MtrlMatcher> matchers)
    {
        super();
        this.matchers = matchers;
        this.index = 0;
        Collections.sort(matchers);
    }

    @Override
    public void doMatch(MaterialMatchContext materialContext) throws MtrlMatchException
    {
        if (this.matchers == null || this.matchers.size() == this.index)
        {
            if (logger.isDebugEnabled())
            {
                logger.debug(" we've reached the end of the match chain.");
            }
            // if you like,you can do something here.
        }
        else
        {
            if (logger.isDebugEnabled())
            {
                logger.debug("Invoking matcher at index [" + this.index + "]");
            }
        //向下执行
this.matchers.get(this.index++).doMatch(materialContext, this); } } @Override public void reset() { this.index = 0; } }
public class MatchChainFactory
{

	//创建识别过滤器链
	public static MatchChain createMatchChain()
	{
		return ApplicationContextUtil.getBean("matchChainFactoryBean", MatchChain.class);
	}

}

  

@Component
public class MatchChainFactoryBean implements FactoryBean<MatchChain>, ApplicationContextAware, InitializingBean
{
    private static final Logger logger = LoggerFactory.getLogger(MatchChainFactoryBean.class);

    private ApplicationContext applicationContext;

    //数组形式的责任链,他通过一个index来驱动请求向下执行
    private List<MtrlMatcher> matchers;

    @Override
    public MatchChain getObject() throws Exception
    {
        if (logger.isDebugEnabled())
        {
            logger.debug("Create MatchChain Instance...");
        }

        return new MatchChainImpl(matchers);
    }

    @Override
    public Class<?> getObjectType()
    {
        return MatchChain.class;
    }

    @Override
    public boolean isSingleton()
    {
        return false;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
    {
        this.applicationContext = applicationContext;
    }
  //添加匹配器
    @Override
    public void afterPropertiesSet() throws Exception
    {
        if (logger.isDebugEnabled())
        {
            logger.debug("Create Matcher Instance Map...");
        }

        matchers = new ArrayList<MtrlMatcher>();
        Map<String, ComparableMatcher> matcherInstanceMap = applicationContext.getBeansOfType(ComparableMatcher.class);
        if (matcherInstanceMap != null && !matcherInstanceMap.isEmpty())
        {
            for (Entry<String, ComparableMatcher> matcher : matcherInstanceMap.entrySet())
            {
                matchers.add(matcher.getValue());
            }
        }
    }
}    

这里通过priority来确定匹配器的使用,决定哪个跳过,那个执行;index则是用来驱动请求向下执行。

当今应用:Dubbo、Mybatis对责任链模式都有不同实现手段,有兴趣可以去了解下。

猜你喜欢

转载自www.cnblogs.com/lias/p/9373232.html