zoukankan      html  css  js  c++  java
  • 从王者荣耀看设计模式(十九.职责链模式)

    从王者荣耀看设计模式(职责链模式)

    一.简介

    王者荣耀一共有7个段位,分别为青铜、白银、黄金、铂金、钻石、星耀、王者。排位模式中,每赢一局就能获得一颗星反之则失去一颗星。获得的星数与段位存在一种联系,当星数达到一定的程度,系统会匹配出相应的段位。

    二.模式动机

    在很多情况下,可以处理某个请求的对象不止一个。很多对象都可以处理申请,而且它们构成一条链,请求沿着这条链传递,这条链就称为职责链。
    职责链可以是一条直线、一个环或者一个树形状,最常见的职责链是直线型,即沿着一条单向的链来传递请求。链上的每个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并使请求沿着链传递,由链上的处理者对请求进行相应的处理,客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可。将请求的发送者和请求的处理者解耦,这就是职责链的模式动机
    在本实例中,星的数量先从青铜类评定,评定不了会之职责链后面传递,知道被处理

    三.职责链模式

    职责链模式(Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求。直到有对象处理它为止。它是一种对象行为型模式

    职责链模式的使用场景:
    在以下情况下可以使用职责链模式:
    ■ 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定,客户端只需将请求提交到链上,无须关心请求的处理对象是谁以及它是如何处理的
    ■ 在不明确指定接收者的情况下,由多个对象中的一个提交一个请求。请求的发送者与请求者的处理者解耦,请求将沿着链进行传递,寻求相应的处理者
    ■ 可动态指定一组对象处理请求。还可以改变链中处理者之间的先后次序

    职责链模式涉及的设计原则有:
    ★ 为交互对象之间松耦合设计而努力
    ★ 类应该只有一个引起变化的原因
    ★ 软件实体应该是可以扩展的,不可以修改的(在系统中增加请求处理类,只需在客户端重新建链即可)

    职责链模式通用类图

    职责链模式涉及的角色:
    职责链模式包含以下角色:
    Handler(抽象处理者)
    抽象处理者定义了一个处理请求的接口,它一般设计为抽象类,由于不同的具体处理者处理请求的方式不同,因此在其中定义了抽象请求处理方法。因为每个处理者的下家还是一个处理者,因此在抽象处理中定义了一个自类型(抽象处理者类型)的对象,作为其对下家的引用。通过该引用,处理者可以连为一条链
    ConcreteHandler(具体处理类)
    具体处理类是抽象处理类的子类,它可以处理用户请求,在具体处理者类中实现了抽象处理者中定义的抽象请求处理方法,在处理请求之前需要进行判断,看是否有对应的处理权限,如果可以处理请求就处理它,否则将请求转发给后继者;在具体处理类中可以访问链中下一个对象,以便请求转发
    Client(客户类)
    客户类用于向链中的对象提出最初的请求,客户类只用关心链的源头,而无须关心请求的处理细节以及请求的传递过程

    职责链模式优点:
    ⑴. 降低耦合度
    ⑵. 可简化对象的相互连接:请求处理对象仅需维持一个指向后继者的引用
    ⑶. 增强给对象指派职责的灵活性:可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责。
    ⑷. 增加新的请求处理类很方便

    职责链模式缺点:
    ⑴. 不能保证请求一定被接收:没有明确接收者,不能确保一定被处理
    ⑵. 对于太长的职责链,影响系统性能。建链不当可能出现死循环。

    四.结构图

    五.设计类图

    为了表示方便,将王者荣耀7个段位简略表示为三个段位:青铜,白银,星耀,王者。星数量少于15,对应段位为青铜;星数量在15-35之间对应段位为白银;星数在35-55之间对应段位为星耀;多于55颗星,表示为王者(X-55)星。

    六.代码实现

    创建请求类(StarRatingRequest)

    package com.chainOfRes.request;
    /*
     * 创建请求类,由客户端指定其属性
     * @param playerName玩家名称
     * @param starNumber星的数量
     */
    public class StarRatingRequest {
    	private String playerName;
    	private int starNumber;
    	
    	public StarRatingRequest(String _playerName,int _starNumber) {
    		this.playerName = _playerName;
    		this.starNumber = _starNumber;
    	}
    
    	public String getPlayerName() {
    		return playerName;
    	}
    
    	public void setPlayerName(String playerName) {
    		this.playerName = playerName;
    	}
    
    	public int getStarNumber() {
    		return starNumber;
    	}
    
    	public void setStarNumber(int starNumber) {
    		this.starNumber = starNumber;
    	}	
    }
    

    创建抽象处理者类(GameLevel)

    package com.chainOfRes.Chain;
    
    import com.chainOfRes.request.StarRatingRequest;
    /*
     * 创建抽象处理者类
     */
    public abstract class GameLevel {
    	//定义自类型
    	protected GameLevel successor;
    	//接收下一家对象
    	public void setSuccessor(GameLevel successor) {
    		this.successor = successor;
    	}
    	//抽象处理方法
    	public abstract void handleRequest(StarRatingRequest request);
    }
    

    创建具体处理者类(Bronze)

    package com.chainOfRes.Chain;
    
    import com.chainOfRes.request.StarRatingRequest;
    /*
     * 创建具体处理者类
     * 当客户端传入的星数少于15,由该对象处理,否则传递给客户端指定的下家
     */
    public class Bronze extends GameLevel {
    	@Override
    	public void handleRequest(StarRatingRequest request) {
    		if(request.getStarNumber() < 15) {
    			System.out.println("玩家[" + request.getPlayerName() + "]统计为" 
    		+ request.getStarNumber() + "颗星,评定为等级:★青铜");
    		}else {
    			if(this.successor != null) {
    				this.successor.handleRequest(request);
    			}
    		}
    	}
    }
    

    创建具体处理类(Silver)

    package com.chainOfRes.Chain;
    
    import com.chainOfRes.request.StarRatingRequest;
    /*
     * 创建具体处理者类
     * 当客户端传入的星数在15-35,由该对象处理,否则传递给客户端指定的下家
     */
    public class Silver extends GameLevel {
    	@Override
    	public void handleRequest(StarRatingRequest request) {
    		if(request.getStarNumber() < 35) {
    			System.out.println("玩家[" + request.getPlayerName() 
    			+ "]统计为" + request.getStarNumber() + "颗星,评定为等级:★白银");
    		}else {
    			if(this.successor != null) {
    				this.successor.handleRequest(request);
    			}
    		}
    	}
    }
    

    创建具体处理类(Royalty)

    package com.chainOfRes.Chain;
    
    import com.chainOfRes.request.StarRatingRequest;
    /*
     * 创建具体处理者类
     * 当客户端传入的星数在35-55,由该对象处理,否则评定为王者段位
     */
    public class Royalty extends GameLevel {
    	@Override
    	public void handleRequest(StarRatingRequest request) {
    		if(request.getStarNumber() < 55) {
    			System.out.println("玩家[" + request.getPlayerName() + "统计为" 
    					+ request.getStarNumber() + "颗星,评定为等级:★星耀");
    		}else {
    			System.out.println("玩家[" + request.getPlayerName() 
    			+ "]统计为" + request.getStarNumber() 
    			+ "颗星,评定为等级:★王者" + (request.getStarNumber()-55) + "星");
    		}
    	}
    }
    

    创建客户测试类(Client类)

    package com.chainOfRes.Client;
    
    import com.chainOfRes.Chain.Bronze;
    import com.chainOfRes.Chain.GameLevel;
    import com.chainOfRes.Chain.Royalty;
    import com.chainOfRes.Chain.Silver;
    import com.chainOfRes.request.StarRatingRequest;
    
    public class Client {
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		//1.实例化具体处理者对象
    		GameLevel objBronze,objSilver,objRoyalty;
    		
    		objBronze = new Bronze();
    		objSilver = new Silver();
    		objRoyalty = new Royalty();
    		//2.为具体处理者配置下一个处理,形成链
    		objBronze.setSuccessor(objSilver);
    		objSilver.setSuccessor(objRoyalty);
    		//3.实例化请求对象
    		StarRatingRequest sr0 = new StarRatingRequest("阿肥",52);
    		//4.将请求发送给链的初始对象
    		objBronze.handleRequest(sr0);
    		
    		StarRatingRequest sr1 = new StarRatingRequest("妙乌",58);
    		objBronze.handleRequest(sr1);
    		
    		StarRatingRequest sr2 = new StarRatingRequest("蒸血Stalk",32);
    		objBronze.handleRequest(sr2);
    		
    		StarRatingRequest sr3 = new StarRatingRequest("文轩",10);
    		objBronze.handleRequest(sr3);
    	}
    }
    

    运行结果:

    七.源代码下载

    从王者荣耀看设计模式(职责链模式)

  • 相关阅读:
    PHP数据库连接mysql与mysqli的区别与用法
    PHP自定义环境搭建(apache、php)
    2021-11-04 CCPC女生赛 ABCDGIK 题解
    Virtual Judge 20211026 日常训练 ABCDEFG题解
    Spring AOP:@DeclareParents 为对象添加方法
    Spring AOP:@Around 的 JavaConfig 写法
    Spring AOP:@Before、@After 的 JavaConfig 写法
    spring事务传播属性
    缓存与数据库的一致性问题怎么解决
    Java多线程之CyclicBarrier
  • 原文地址:https://www.cnblogs.com/miaowulj/p/12173411.html
Copyright © 2011-2022 走看看