java设计模式————委派模式,天天使用却不知道的模式,手撸spring
委派模式(Delegate Pattern): 基本作用就是负责任务的调度和分配任务,跟代理模式很像,可以看做是一种特殊情况下的静态代理的全权代理,但是代理模式注重过程,而委派模式注重结果。
不属于gof23种设计模式之一。
属于行为型模式。
现实场景:
老板要做一些事情,只需要交代给经理,由经理分发给对应的员工即可
【java设计模式————委派模式,天天使用却不知道的模式,手撸spring】
文章图片
代码:
/**
* @Author Darker
* @Descrption 老板
* @Date : Created in 10:37 2020-3-12
*/
public class Boss {//委派什么任务给经理
public void delegate(String task,Leader leader){
leader.doing(task);
}
}/**
* @Author Darker
* @Descrption被委派的经理,存储他统管的所有员工
* @Date : Created in 10:37 2020-3-12
*/
public class Leader {
//要知道每个员工的特长何特征
private Map register = new HashMap<>();
public Leader(){
register.put("数据库",new Aemployee());
register.put("业务逻辑",new Bemployee());
}//分配对应的任务给对应的员工
public void doing(String task){
register.get(task).doingSomeThings(task);
}
}/**
* @Author Darker
* @Descrption 员工抽象
* @Date : Created in 10:38 2020-3-12
*/
public interface IEmployee {public void doingSomeThings(String task);
}/**
* @Author Darker
* @Descrption
* @Date : Created in 10:39 2020-3-12
*/
public class Aemployee implements IEmployee{
@Override
public void doingSomeThings(String task) {
System.out.println("我是a员工,我负责做数据库的工作,我做了"+task+"任务");
}
}/**
* @Author Darker
* @Descrption
* @Date : Created in 10:40 2020-3-12
*/
public class Bemployee implements IEmployee{
@Override
public void doingSomeThings(String task) {
System.out.println("我是b员工,我负责做业务开发的工作,我做了"+task+"任务");
}
}
执行结果:
现在老板需要委派一个数据库的任务给经理,获得反馈
/**
* @Author Darker
* @Descrption
* @Date : Created in 10:57 2020-3-12
*/
public class DelegateTest {
public static void main(String[] args) {
new Boss().delegate("数据库",new Leader());
}
}
文章图片
分析一下,老板相当于需求,现在有一个经理类来帮老板分发任务,所以经理需要知道所有员工,以及每个员工对应的任务,用一个私有的map存了所有员工以及对应的任务,当收到一个任务时,可以很快的安排对应的任务给对应的员工,这种模式有点像静态代理。
类之间的关系:
文章图片
那么问题来了,我们写代码到底在哪里会用到委派模式呢,不急我们先来看一段代码,看完你就知道了。
/**
* @Author Darker
* @Descrption 请求处理Servlet
* @Date : Created in 11:14 2020-3-12
*/
public class DispatcherServlet extends HttpServlet{@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
delegate(req,resp);
}public void delegate(HttpServletRequest req, HttpServletResponse resp){
String reqUrl = req.getRequestURI();
if ("getOrderById".equals(reqUrl)){
new OrderController().getOrderById();
}else if("logout".equals(reqUrl)){
new SystemController().logout();
}else{
System.out.println("访问路径不存在 404");
}
}
}/**
* @Author Darker
* @Descrption 订单业务Controller
* @Date : Created in 11:15 2020-3-12
*/
public class OrderController {public void getOrderById(){}
}/**
* @Author Darker
* @Descrption 系统操作Controller
* @Date : Created in 11:28 2020-3-12
*/
public class SystemController {public void logout(){}
}
发现了没有,我们浏览器输入的访问地址都是走servlet,然后servlet来帮我们分派到你要调用的service中并且决定调用哪一个方法,这是不是就是策略模式呢,我们上面写的代码就是一个简易的分配逻辑。
好了,这就是委派模式了,它是一种比较简单的设计模式,但是和其它模式结合在一起也对代码的优化起到了不可忽视的作用。
补充:
上面最后的处理有点粗糙,所以本人参考spring的源码又做了些补充,是学习spring的思想来写的,下面是改进后的代码。
/**
* @Author Darker
* @Descrption 请求处理Servlet
* @Date : Created in 11:14 2020-3-12
*/
public class DispatcherServlet extends HttpServlet{private List handlerMapping = new ArrayList<>();
//初始化的时候把controller和访问路径,方法绑定在一个list里面
@Override
public void init() throws ServletException {
Class> orderControllerClass =OrderController.class;
try {
handlerMapping.add(new Handler()
.setController(orderControllerClass.newInstance())
.setMeThod(orderControllerClass.getMethod("getOrderById"))
.setUrl("/web/getMemberById.json")
);
} catch (Exception e) {
e.printStackTrace();
}}@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
delegate(req,resp);
}public void delegate(HttpServletRequest req, HttpServletResponse resp){
String reqUrl = req.getRequestURI();
Handler handler = null;
for(Handler h :handlerMapping){
if(reqUrl.equals(h.getUrl())){
handler = h;
break;
}
}try {
Object o = handler.getMeThod().invoke(handler.getController(),null);
try {
resp.getWriter().write(o.toString());
} catch (IOException e) {
e.printStackTrace();
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}/* if ("getOrderById".equals(reqUrl)){
new OrderController().getOrderById();
}else if("logout".equals(reqUrl)){
new SystemController().logout();
}else{
System.out.println("访问路径不存在 404");
}*/
}//绑定的类,模仿lombok的链式调用
class Handler{
privateObject controller;
private Method meThod;
private String url;
public Object getController() {
return controller;
}public Handler setController(Object controller) {
this.controller = controller;
return this;
}public Method getMeThod() {
return meThod;
}public Handler setMeThod(Method meThod) {
this.meThod = meThod;
return this;
}public String getUrl() {
return url;
}public Handler setUrl(String url) {
this.url = url;
return this;
}
}
}
推荐阅读
- 编程语言|Node 之父斥责 Oracle(你们也不用,那请交出 JavaScript 商标!)
- 第五章|第五章 内存管理—第30条:以ARC简化引用计数
- mysql|工作随笔(一)——docker和mysql容器搭建使用问题解决
- 网络|安全防御——防火墙一
- 网络|安全防御——防火墙二
- 有时,人性本恶
- 数据结构与算法|数据结构学习笔记 6-1 手撕AVL树 与 LeetCode真题(Java)
- linux|SD卡烧写Linux kernel——SD卡分区,并烧写uboot,kernel,DTB及filesystem
- JavaScript|使用JS+socket.io+WebRTC+nodejs+express搭建一个简易版远程视频聊天
- 沈星移———猫系外表犬系心的小公举