使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止java
假设如今开发一个在线订购系统。但愿对系统访问进行限制,只容许认证用户建立订单。但是,在接下来的几个月里,不断有新的需求提了出来....缓存
检查代码原本就已经混乱不堪,而每次新增功能都会使其更加臃肿。修改某个检查步骤有时会影响其余的检查步骤。系统会变得让人很是费解,并且其维护成本也会激增安全
责任链会将特定行为转换为被称做处理者的独立对象。每一个检查步骤均可被抽取为仅有单个方法的类,并执行检查操做。请求及其数据则会被做为参数传递给该方法。而且,链上的每一个处理者都有一个成员变量来保存对于下一处理者的引用。处理者接收到请求后自行决定是否可以对其进行处理。若是本身可以处理,处理者就再也不继续传递请求。不然,请求会在链上移动, 直至全部处理者都有机会对其进行处理。所以在这种状况下,每一个请求要么最多有一个处理者对其进行处理,要么没有任何处理者对其进行处理 oop
1)单一职责原则。 可对发起操做和执行操做的类进行解耦flex
2)开闭原则。 能够在不更改现有代码的状况下在程序中新增处理者ui
3)加强了给对象指派职责的灵活性this
4)请求可能一直到链的末端都得不处处理spa
middleware/Middleware.java: 基础验证接口code
package chain_of_responsibility.middleware; /** * @author GaoMing * @date 2021/7/21 - 21:16 */ public abstract class Middleware { private Middleware next; /** * Builds chains of middleware objects. */ public Middleware linkWith(Middleware next) { this.next = next; return next; } /** * Subclasses will implement this method with concrete checks. */ public abstract boolean check(String email, String password); /** * Runs check on the next object in chain or ends traversing if we're in * last object in chain. */ protected boolean checkNext(String email, String password) { if (next == null) { return true; } return next.check(email, password); } }
middleware/ThrottlingMiddleware.java: 检查请求数量限制component
package chain_of_responsibility.middleware; /** * @author GaoMing * @date 2021/7/21 - 21:16 */ public class ThrottlingMiddleware extends Middleware{ private int requestPerMinute; private int request; private long currentTime; public ThrottlingMiddleware(int requestPerMinute) { this.requestPerMinute = requestPerMinute; this.currentTime = System.currentTimeMillis(); } /** * Please, not that checkNext() call can be inserted both in the beginning * of this method and in the end. * * This gives much more flexibility than a simple loop over all middleware * objects. For instance, an element of a chain can change the order of * checks by running its check after all other checks. */ public boolean check(String email, String password) { if (System.currentTimeMillis() > currentTime + 60_000) { request = 0; currentTime = System.currentTimeMillis(); } request++; if (request > requestPerMinute) { System.out.println("Request limit exceeded!"); Thread.currentThread().stop(); } return checkNext(email, password); } }
middleware/UserExistsMiddleware.java: 检查用户登陆信息
package chain_of_responsibility.middleware; import chain_of_responsibility.server.Server; /** * @author GaoMing * @date 2021/7/21 - 21:16 */ public class UserExistsMiddleware extends Middleware{ private Server server; public UserExistsMiddleware(Server server) { this.server = server; } public boolean check(String email, String password) { if (!server.hasEmail(email)) { System.out.println("This email is not registered!"); return false; } if (!server.isValidPassword(email, password)) { System.out.println("Wrong password!"); return false; } return checkNext(email, password); } }
middleware/RoleCheckMiddleware.java: 检查用户角色
package chain_of_responsibility.middleware; /** * @author GaoMing * @date 2021/7/21 - 21:17 */ public class RockCheckMiddleware extends Middleware{ public boolean check(String email, String password) { if (email.equals("admin@example.com")) { System.out.println("Hello, admin!"); return true; } System.out.println("Hello, user!"); return checkNext(email, password); } }
server/Server.java: 受权目标
package chain_of_responsibility.server; import chain_of_responsibility.middleware.Middleware; import java.util.HashMap; import java.util.Map; /** * @author GaoMing * @date 2021/7/21 - 21:22 */ public class Server { private Map<String, String> users = new HashMap<>(); private Middleware middleware; /** * Client passes a chain of object to server. This improves flexibility and * makes testing the server class easier. */ public void setMiddleware(Middleware middleware) { this.middleware = middleware; } /** * Server gets email and password from client and sends the authorization * request to the chain. */ public boolean logIn(String email, String password) { if (middleware.check(email, password)) { System.out.println("Authorization have been successful!"); // Do something useful here for authorized users. return true; } return false; } public void register(String email, String password) { users.put(email, password); } public boolean hasEmail(String email) { return users.containsKey(email); } public boolean isValidPassword(String email, String password) { return users.get(email).equals(password); } }
Demo.java: 客户端代码
package chain_of_responsibility; import chain_of_responsibility.middleware.Middleware; import chain_of_responsibility.middleware.RockCheckMiddleware; import chain_of_responsibility.middleware.ThrottlingMiddleware; import chain_of_responsibility.middleware.UserExistsMiddleware; import chain_of_responsibility.server.Server; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * @author GaoMing * @date 2021/7/21 - 21:15 */ public class Demo { private static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); private static Server server; private static void init() { server = new Server(); server.register("admin@example.com", "admin_pass"); server.register("user@example.com", "user_pass"); // All checks are linked. Client can build various chains using the same // components. Middleware middleware = new ThrottlingMiddleware(2); middleware.linkWith(new UserExistsMiddleware(server)) .linkWith(new RockCheckMiddleware()); // Server gets a chain from client code. server.setMiddleware(middleware); } public static void main(String[] args) throws IOException { init(); boolean success; do { System.out.print("Enter email: "); String email = reader.readLine(); System.out.print("Input password: "); String password = reader.readLine(); success = server.logIn(email, password); } while (!success); } }
执行结果
Enter email: admin@example.com Input password: admin_pass Hello, admin! Authorization have been successful! Enter email: user@example.com Input password: user_pass Hello, user! Authorization have been successful!
责任链模式、命令模式、中介者模式和观察者模式用于处理请求发送者和接收者之间的不一样链接方式:
1. 责任链按照顺序将请求动态传递给一系列的潜在接收者,直至其中一名接收者对请求进行处理
2. 命令在发送者和请求者之间创建单向链接
3. 中介者清除了发送者和请求者之间的直接链接, 强制它们经过一个中介对象进行间接沟通
4. 观察者容许接收者动态地订阅或取消接收请求
例如,当用户点击按钮时,按钮产生的事件将沿着GUI元素链进行传递,最开始是按钮的容器(如窗体或面板),直至应用程序主窗口。链上第一个能处理该事件的元素会对其进行处理
使用示例:责任链模式在Java程序中并不常见,由于它仅在代码与对象链打交道时才能发挥做用。该模式最流行的使用案例之一是在GUI类中将事件向上传递给父组件。另外一个值得注意的使用案例是依次访问过滤器
下面是该模式在核心 Java 程序库中的一些示例:
识别方法:该模式可经过一组对象的行为方法间接调用其余对象的相同方法来识别,并且全部对象都会遵循相同的接口