委派模式和策略模式筆記

委派模式和策略模式

委派模式

什么是委派模式巍实?

維基百科對(duì)委派模式的解釋是:委派模式(delegation pattern)是軟件設(shè)計(jì)模式中的一項(xiàng)基本技巧。在委派模式中呛占,有兩個(gè)對(duì)象參與處理同一個(gè)請(qǐng)求,接受請(qǐng)求的對(duì)象將請(qǐng)求委托給另一個(gè)對(duì)象來(lái)代理挨务。

委派模式的基本作用就是負(fù)責(zé)任務(wù)的調(diào)用和分配任務(wù)紧武,跟代理模式很像剃氧,可以看做是一種特殊情況下的靜態(tài)代理的全權(quán)代理,但是代理模式注重過(guò)程阻星,而委派模式注重結(jié)果朋鞍。委派模式在Spring中應(yīng)用非常多,大家常用的DispatcherServlet其實(shí)就是用到了委派模式⊥谆現(xiàn)實(shí)生活中也常有委派的場(chǎng)景發(fā)生滥酥。例如:教室要進(jìn)行大掃除,老師(Teacher)布置任務(wù)給班長(zhǎng)(Monitor)矾踱,班長(zhǎng)再根據(jù)任務(wù)分配給學(xué)生(Student)恨狈,我們以代碼的形式進(jìn)行模擬一下疏哗。

/**
 * @author: Winston
 * @createTime: 2021/6/24
 *
 * 老師
 */
public class Teacher {


    /**
     * 給班長(zhǎng)下發(fā)命令
     * @param command
     * @param monitor
     */
    public void command(String command, Monitor monitor){
        monitor.doing(command);
    }

}

/**
 * @author: Winston
 * @createTime: 2021/6/24
 * 學(xué)生聽(tīng)指令的接口
 */
public interface IStudent {

    /**
     * 根據(jù)指令做事
     * @param command
     */
    void doing(String command);

}


/**
 * @author: Winston
 * @createTime: 2021/6/24
 *
 * 班長(zhǎng)
 */
public class Monitor implements IStudent{

    /**
     * map用來(lái)存放接收指令的學(xué)生呛讲,key是指令  map 是學(xué)生
     */
    private Map<String,IStudent>  studentMap = new HashMap<>();

    public Monitor(){
        studentMap.put("掃地",new StudentA());
        studentMap.put("擦黑板",new StudentB());
    }

    /**
     * 班長(zhǎng)不干活,根據(jù)指令給學(xué)生分派任務(wù)
     * @param command
     */
    @Override
    public void doing(String command) {
        studentMap.get(command).doing(command);
    }
}

/**
 * @author: Winston
 * @createTime: 2021/6/24
 */
public class StudentA implements IStudent {

    @Override
    public void doing(String command) {
        System.out.println("我是StudentA返奉,我大掃除的職責(zé)是,"+command);
    }
}

/**
 * @author: Winston
 * @createTime: 2021/6/24
 */
public class StudentB implements IStudent {

    @Override
    public void doing(String command) {
        System.out.println("我是StudentB贝搁,我大掃除的職責(zé)是,"+command);
    }
}

測(cè)試類(lèi)

/**
 * @author: Winston
 * @createTime: 2021/6/24
 */
public class DelegateTest {
    public static void main(String[] args) {
        //客戶(hù)請(qǐng)求(Teacher)、委派者(Monitor)芽偏、被被委派者(Student)
        //委派者要持有被委派者的引用
        //代理模式注重的是過(guò)程雷逆, 委派模式注重的是結(jié)果
        //策略模式注重是可擴(kuò)展(外部擴(kuò)展),委派模式注重內(nèi)部的靈活和復(fù)用
        //委派的核心:就是分發(fā)污尉、調(diào)度膀哲、派遣
        //委派模式:就是靜態(tài)代理和策略模式一種特殊的組合
        new Teacher().command("掃地", new Monitor());
    }
}


運(yùn)行結(jié)果:我是StudentA,我大掃除的職責(zé)是,掃地

委派模式在SpringMVC源碼中的體現(xiàn)

下面我們來(lái)簡(jiǎn)單模擬一下SpringMVC的DispatcherServlet是怎么實(shí)現(xiàn)委派模式的被碗。先創(chuàng)建幾個(gè)Controller

/**
 * @author: Winston
 * @createTime: 2021/6/24
 */
public class UserController {

    public void findUserById(String id){
    }
}

/**
 * @author: Winston
 * @createTime: 2021/6/24
 */
public class OrderController {

    public void findOrderById(String id){
    }
}
/**
 * @author: Winston
 * @createTime: 2021/6/24
 */
public class IndexController {

    public void index(){

    }
}

創(chuàng)建一個(gè)DispatcherServlet用于分發(fā)請(qǐng)求


/**
 * 這個(gè)類(lèi)就相當(dāng)于是班長(zhǎng)角色
 * @author: Winston
 * @createTime: 2021/6/24
 */
public class DispatcherServlet extends HttpServlet {
    private void doDispatcher(HttpServletRequest request, HttpServletResponse response){

        String requestURI = request.getRequestURI();
        String id = request.getParameter("id");


        // 根據(jù)uri判斷分發(fā)請(qǐng)求到Controller
        if("findUserById".equals(requestURI)){
            new UserController().findUserById(id);
        }else if("findOrderById".equals(requestURI)){
            new OrderController().findOrderById(id);
        }else if("index".equals(requestURI)){
            new IndexController().index();
        }else {
            try {
                response.getWriter().write("404 NOT FOUND");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

配置web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:javaee="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
    <display-name>Gupao Web Application</display-name>


    <servlet>
        <servlet-name>delegateServlet</servlet-name>
        <servlet-class>com.gupaoedu.vip.pattern.delegate.mvc.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>delegateServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>


</web-app>


小結(jié)

一個(gè)模擬委派模式的簡(jiǎn)單DispatcherServlet就寫(xiě)完了某宪。Spring中有許多地方都用到了委派模式,我們可以通過(guò)命名來(lái)識(shí)別锐朴,只要是以Delegate結(jié)尾的都是事先了委派模式兴喂。例如:BeanDefinitionParserDelegate 根據(jù)不同類(lèi)型委派不同邏輯解析BeanDefinition。

策略模式

策略模式概念

首先了解一下策略模式的概念焚志,在策略模式(Strategy Pattern)中衣迷,一個(gè)類(lèi)的行為或其算法可以在運(yùn)行時(shí)更改。這種類(lèi)型的設(shè)計(jì)模式屬于行為型模式酱酬。

策略模式的應(yīng)用場(chǎng)景

1壶谒、假如系統(tǒng)中有很多類(lèi),而他們的區(qū)別僅僅在于他們的行為不同膳沽。

2汗菜、一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種泼差。

案例一

上面對(duì)策略模式的介紹都比較抽象不太好理解,舉個(gè)生活中的小例子呵俏,在我們進(jìn)行網(wǎng)上購(gòu)物時(shí)如果遇到一些活動(dòng)商家會(huì)給商品以某些形式降價(jià)堆缘,比如優(yōu)惠券、拼團(tuán)普碎、返現(xiàn)吼肥。下面我們通過(guò)用代碼來(lái)模擬一下。

首先創(chuàng)建一個(gè)促銷(xiāo)活動(dòng)Promotion接口麻车,所有的降價(jià)形式都要實(shí)現(xiàn)這個(gè)接口缀皱。

/**
 * @author: Winston
 * @createTime: 2021/6/25
 *
 * 促銷(xiāo)活動(dòng)
 */
public interface Promotion {

    /**
     * 活動(dòng)內(nèi)容
     */
    void activity();
}

無(wú)優(yōu)惠活動(dòng)的 EmptyActivity類(lèi)

public class EmptyActivity implements Promotion{
    @Override
    public void activity() {
        System.out.println("無(wú)促銷(xiāo)活動(dòng)");
    }
}

優(yōu)惠券活動(dòng)

public class CouponActivity implements Promotion {
    @Override
    public void activity() {
        System.out.println("優(yōu)惠券立減20");
    }
}

返現(xiàn)活動(dòng)

public class CashbackActivity implements Promotion {
    @Override
    public void activity() {
        System.out.println("購(gòu)買(mǎi)立馬返現(xiàn)15");
    }
}

組團(tuán)活動(dòng)

public class GroupActivity implements Promotion {
    @Override
    public void activity() {
        System.out.println("兩人拼團(tuán)立減25");
    }
}

促銷(xiāo)方案類(lèi)PromotionActivity

/**
 * @author: Winston
 * @createTime: 2021/6/25
 *
 * 舉辦的促銷(xiāo)活動(dòng)
 */
public class PromotionActivity {
    private Promotion promotion;

    public PromotionActivity(Promotion promotion) {
        this.promotion = promotion;
    }


    public void execute(){
        promotion.activity();
    }
}

測(cè)試類(lèi):

public class PromotionTest {
    public static void main(String[] args) {
        // 不同活動(dòng)對(duì)應(yīng)不同的優(yōu)惠策略,默認(rèn)策略是無(wú)優(yōu)惠
        PromotionActivity promotionActivity = null;
        String promotionKey = "anniversary";
        if ("doubleEleven".equals(promotionKey)) {
            // 雙十一活動(dòng)动猬,優(yōu)惠券
            promotionActivity = new PromotionActivity(new CouponActivity());
        } else if ("activity618".equals(promotionKey)) {
            // 618啤斗,返現(xiàn)
            promotionActivity = new PromotionActivity((new CashbackActivity()));
        } else if ("anniversary".equals(promotionKey)) {
            // 店慶,組團(tuán)
            promotionActivity = new PromotionActivity((new GroupActivity()));
        } else {
            promotionActivity = new PromotionActivity(new EmptyActivity());
        }
        promotionActivity.execute();
    }
}

從上面的測(cè)試代碼可以看出赁咙,如果又增加了一個(gè)促銷(xiāo)活動(dòng)钮莲,那么我們就又要加上新活動(dòng),增加if else彼水,相當(dāng)于又修改了業(yè)務(wù)代碼崔拥,那么又要進(jìn)行測(cè)試,如此一來(lái)工作量難免是重復(fù)且耗時(shí)的凤覆,下面我們結(jié)合工廠模式和單例模式對(duì)其進(jìn)行改造链瓦,在這里說(shuō)一下,設(shè)計(jì)模式一般都不是單獨(dú)出現(xiàn)的盯桦,而是結(jié)合使用慈俯。

創(chuàng)建一個(gè)存放活動(dòng)策略key的枚舉,PromotionEnum

/**
 * @author: Winston
 * @createTime: 2021/6/25|
 *
 * 促銷(xiāo)活動(dòng)策略的enum
 */
public enum PromotionEnum {
    COUPON_ACTIVITY("優(yōu)惠券活動(dòng)","COUPON_ACTIVITY"),
    CASHBACK_ACTIVITY("返現(xiàn)活動(dòng)","CASHBACK_ACTIVITY"),
    GROUP_ACTIVITY("組團(tuán)活動(dòng)","GROUP_ACTIVITY")
    ;


    /**
     * 活動(dòng)名稱(chēng)
     */
    private String activityName;
    /**
     * 活動(dòng)key
     */
    private String promotionKey;

    PromotionEnum(String activityName, String promotionKey) {
        this.activityName = activityName;
        this.promotionKey = promotionKey;
    }

    public String getActivityName() {
        return activityName;
    }

    public void setActivityName(String activityName) {
        this.activityName = activityName;
    }

    public String getPromotionKey() {
        return promotionKey;
    }

    public void setPromotionKey(String promotionKey) {
        this.promotionKey = promotionKey;
    }
}

創(chuàng)建促銷(xiāo)策略工廠PromotionFactory

/**
 * @author: Winston
 * @createTime: 2021/6/25
 * 促銷(xiāo)策略工廠
 */
public class PromotionFactory {
    /**
     * 活動(dòng)
     */
    private static Promotion promotion;
    /**
     * 存放活動(dòng)策略的map拥峦,Key是活動(dòng)名稱(chēng)贴膘,value是具體活動(dòng)
     */
    private static Map<String, Promotion> promotionMap = new HashMap<>();
    /**
     * 默認(rèn)策略,無(wú)優(yōu)惠
     */
    private static final EmptyActivity emptyActivity = new EmptyActivity();

    static {
        promotionMap.put(PromotionEnum.COUPON_ACTIVITY.getPromotionKey(), new CouponActivity());
        promotionMap.put(PromotionEnum.CASHBACK_ACTIVITY.getPromotionKey(), new CashbackActivity());
        promotionMap.put(PromotionEnum.GROUP_ACTIVITY.getPromotionKey(), new GroupActivity());
    }

    /**
     * 根據(jù)活動(dòng)key拿到對(duì)應(yīng)的活動(dòng)
     * @param key
     * @return
     */
    public static Promotion getPromotionByKey(String key) {
        promotion = promotionMap.get(key);

        return promotion == null ? emptyActivity : promotion;
    }

}

測(cè)試類(lèi):

public class OptimizePromotionTest {
    public static void main(String[] args) {
        Promotion promotion = PromotionFactory.getPromotionByKey(PromotionEnum.COUPON_ACTIVITY.getPromotionKey());
        promotion.activity();
    }
}

案例二

通過(guò)第一個(gè)案例事镣,我們對(duì)策略模式有了一點(diǎn)了解步鉴,下面再舉一個(gè)例子來(lái)加深對(duì)策略模式的印象。在我們點(diǎn)外賣(mài)進(jìn)行付款時(shí)璃哟,往往有多種支付方式氛琢,比如微信支付、支付寶支付随闪、銀行卡支付阳似、QQ支付等,這些支付方式的選擇其實(shí)也是策略模式的一種體現(xiàn)铐伴,下面我們通過(guò)代碼來(lái)進(jìn)行模擬撮奏。

創(chuàng)建一個(gè)Payment抽象類(lèi)俏讹,定義支付規(guī)范和支付邏輯:

/**
 * @author: Winston
 * @createTime: 2021/6/25
 * <p>
 * 支付工具中所具有的方法
 */
public abstract class Payment {
    /**
     * 支付類(lèi)型
     *
     * @return
     */
    public abstract String getName();

    /**
     * 余額查詢(xún)
     */
    protected abstract Double queryBalance();

    /**
     * 支付方法
     *
     * @param amount  支付金額
     * @param balance 余額
     */
    public PayState pay(Double amount, Double balance) {
        if (balance >= amount) {
            return new PayState(200, "支付成功");
        } else {
            return new PayState(500, "支付失敗,余額不足");
        }
    }

}

創(chuàng)建幾種支付方式畜吊,微信支付泽疆、支付寶支付、qq支付玲献、銀行卡支付

/**
 * @author: Winston
 * @createTime: 2021/6/25
 */
public class WechatPay extends Payment {


    @Override
    public String getName() {
        return "微信支付";
    }

    @Override
    protected Double queryBalance() {
        return 14.43D;
    }
}
/**
 * @author: Winston
 * @createTime: 2021/6/25
 */
public class AliPay extends Payment {


    @Override
    public String getName() {
        return "支付寶支付";
    }

    @Override
    protected Double queryBalance() {
        return 561.24D;
    }
}
/**
 * @author: Winston
 * @createTime: 2021/6/25
 */
public class QqPay extends Payment {


    @Override
    public String getName() {
        return "qq支付";
    }

    @Override
    protected Double queryBalance() {
        return 5.43D;
    }
}
/**
 * @author: Winston
 * @createTime: 2021/6/25
 */
public class CardPay extends Payment {


    @Override
    public String getName() {
        return "銀行卡支付";
    }

    @Override
    protected Double queryBalance() {
        return 20051.15D;
    }
}

創(chuàng)建一個(gè)支付狀態(tài)的包裝類(lèi)PayState

/**
 * @author: Winston
 * @createTime: 2021/6/25
 */
public class PayState {
    /**
     * 狀態(tài)碼
     */
    private int code;

    /**
     * 狀態(tài)信息
     */
    private String msg;

    public PayState(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "PayState{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                '}';
    }
}

創(chuàng)建支付策略管理類(lèi):


/**
 * @author: Winston
 * @createTime: 2021/6/25
 * 支付策略管理
 */
public class PayStrategy {
    public static final String ALI_PAY= "ALI_PAY";
    public static final String WECHAT_PAY= "WECHAT_PAY";
    public static final String CARD_PAY= "CARD_PAY";
    public static final String QQ_PAY= "QQ_PAY";
    public static final String DEFAULT_PAY= ALI_PAY;

    // 存放支付策略的map
    private static Map<String,Payment> paymentMap = new HashMap<>();

    static {
        paymentMap.put(ALI_PAY,new AliPay());
        paymentMap.put(WECHAT_PAY,new WechatPay());
        paymentMap.put(CARD_PAY,new CardPay());
        paymentMap.put(QQ_PAY,new QqPay());
    }

    public static Payment get(String payKey){
        if(!paymentMap.containsKey(payKey)){
            return paymentMap.get(DEFAULT_PAY);
        }
        return paymentMap.get(payKey);
    }

}

創(chuàng)建訂單類(lèi)殉疼,模擬下單支付時(shí)的操作

/**
 * @author: Winston
 * @createTime: 2021/6/25
 * 訂單類(lèi)
 */
public class Order {
    /**
     * 訂單id
     */
    private String id;
    /**
     * 訂單金額
     */
    private Double amount;

    public Order(String id, Double amount) {
        this.id = id;
        this.amount = amount;
    }

    public void pay() {
        pay(PayStrategy.DEFAULT_PAY);
    }

    /**
     * 使用指定支付方式支付
     *
     * @param payKey
     */
    public void pay(String payKey) {
        System.out.println("訂單編號(hào)是:" + this.id);
        System.out.println("支付金額為:" + this.amount);
        Payment payment = PayStrategy.get(payKey);
        System.out.println("支付方式:" + payment.getName());
        PayState pay = payment.pay(this.amount, payment.queryBalance());
        System.out.println(pay);
    }

}

測(cè)試類(lèi):

public class PaymentTest {
    public static void main(String[] args) {
        System.out.println("開(kāi)始下單點(diǎn)外賣(mài):");
        Order order = new Order("10001", 21.31D);
        order.pay(PayStrategy.WECHAT_PAY);
    }
}

運(yùn)行結(jié)果:

開(kāi)始下單點(diǎn)外賣(mài):
訂單編號(hào)是:10001
支付金額為:21.31
支付方式:微信支付
PayState{code=500, msg='支付失敗,余額不足'}

策略模式在JDK源碼中的體現(xiàn)

Comparator接口中的compare()方法捌年,就是一個(gè)策略抽象實(shí)現(xiàn)瓢娜。

    int compare(T o1, T o2);

Comparator 抽象下面有非常多的實(shí)現(xiàn)類(lèi),我們經(jīng)常會(huì)把 Comparator 作為參數(shù)傳入作
為排序策略礼预,例如 Arrays 類(lèi)的 parallelSort 方法等:

public class Arrays {
...
public static <T> void parallelSort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> cmp) {
...
}
...
}

還有TreeMap的構(gòu)造方法:

public class TreeMap<K,V>
extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
    ...
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }
    ...
}

策略模式的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  • 策略模式符合開(kāi)閉原則
  • 避免使用多重條件轉(zhuǎn)移語(yǔ)句眠砾,如if...else...、switch
  • 使用策略模式可以提高算法的保密性和安全性

缺點(diǎn):

  • 客戶(hù)端必須知道所有的策略托酸,并且自行決定使用哪一個(gè)策略類(lèi)
  • 代碼中會(huì)產(chǎn)生非常多的策略類(lèi)褒颈,增加維護(hù)難度

委派模式與策略模式綜合應(yīng)用

在委派模式中我們寫(xiě)了一個(gè)例子模仿了SpringMVC的DispatcherServlet,在那個(gè)例子中我們用了很多的if...else語(yǔ)句获高,在實(shí)際項(xiàng)目中Controller數(shù)量往往很大哈肖,如果都用if..else來(lái)寫(xiě)的話,那么不僅工作量大念秧,而且出錯(cuò)的可能性也很大,下面我們使用委派模式和策略模式將它進(jìn)行改造布疼。

創(chuàng)建一個(gè)Handler類(lèi)摊趾,用于存Method和url對(duì)應(yīng)的關(guān)系

/**
 * @author: Winston
 * @createTime: 2021/6/25
 *
 * 保存Controller的一些信息,將url和method的關(guān)系綁定
 */
public class Handler {

    /**
     * controller的實(shí)例
     */
    private Object controller;

    /**
     * 存放方法
     */
    private Method method;

    /**
     * 對(duì)應(yīng)映射方法的url
     */
    private String url;


    public Handler(Object controller, Method method, String url) {
        this.controller = controller;
        this.method = method;
        this.url = url;
    }

    public Object getController() {
        return controller;
    }

    public void setController(Object controller) {
        this.controller = controller;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

之前寫(xiě)過(guò)的三個(gè)controller

public class UserController {

    public void findUserById(String id){
    }
}


public class OrderController {

    public void findOrderById(String id){
    }
}

public class IndexController {

    public void index(){

    }
}

改造的servlet游两,重寫(xiě)init方法用于模擬在啟動(dòng)時(shí)將各個(gè)controller信息保存到Handler中去砾层,代碼如下:

/**
 * 這個(gè)類(lèi)就相當(dāng)于是班長(zhǎng)角色
 *
 * @author: Winston
 * @createTime: 2021/6/24
 */
public class DispatcherServlet extends HttpServlet {

    // 初始化所有controller的信息存到handlerList中
    public static List<Handler> handlerList = new ArrayList<>();

    /**
     * 模擬controller初始化時(shí)將信息存到handlerList中
     */
    @Override
    public void init() throws ServletException {
        Class<UserController> userControllerClass = UserController.class;
        Class<OrderController> orderControllerClass = OrderController.class;
        Class<IndexController> indexControllerClass = IndexController.class;
        try {
            Handler userHandler = new Handler(userControllerClass.newInstance(),
                    userControllerClass.getMethod("findUserById", new Class[]{String.class}), "/web/findUserById");
            Handler orderHandler = new Handler(orderControllerClass.newInstance(),
                    orderControllerClass.getMethod("findOrderById", new Class[]{String.class}), "/web/findOrderById");
            Handler indexHandler = new Handler(indexControllerClass.newInstance(),
                    indexControllerClass.getMethod("index", null), "/web/index");
            // 將handler添加到list中
            handlerList.add(userHandler);
            handlerList.add(orderHandler);
            handlerList.add(indexHandler);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doDispatcher(req, resp);
    }


    private void doDispatcher(HttpServletRequest request, HttpServletResponse response) {
        // 獲取url
        String requestURI = request.getRequestURI();
        // 要執(zhí)行的handler
        Handler handler = null;
        // 根據(jù)url獲取handler
        for (Handler h : handlerList) {
            if(h.getUrl().equals(requestURI)){
                handler = h;
                break;
            }
        }
        if(handler == null){
            try {
                response.getWriter().write("Not found 404!");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
        // 執(zhí)行方法的結(jié)果
        Object result = null;
        try {
            // 根據(jù)獲取到的執(zhí)行器利用反射執(zhí)行方法,實(shí)際沒(méi)那么簡(jiǎn)單贱案,這里簡(jiǎn)單模擬不用深究
            result =  handler.getMethod().invoke(handler.getController(),request.getParameter("id"));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        // 將結(jié)果返回
        try {
            response.getWriter().write(result.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肛炮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宝踪,更是在濱河造成了極大的恐慌侨糟,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘩燥,死亡現(xiàn)場(chǎng)離奇詭異秕重,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)厉膀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)溶耘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)二拐,“玉大人,你說(shuō)我怎么就攤上這事凳兵“傩拢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵庐扫,是天一觀的道長(zhǎng)吟孙。 經(jīng)常有香客問(wèn)我,道長(zhǎng)聚蝶,這世上最難降的妖魔是什么杰妓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮碘勉,結(jié)果婚禮上巷挥,老公的妹妹穿的比我還像新娘。我一直安慰自己验靡,他們只是感情好倍宾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著胜嗓,像睡著了一般高职。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辞州,一...
    開(kāi)封第一講書(shū)人閱讀 51,727評(píng)論 1 305
  • 那天怔锌,我揣著相機(jī)與錄音,去河邊找鬼变过。 笑死埃元,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的媚狰。 我是一名探鬼主播岛杀,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼崭孤!你這毒婦竟也來(lái)了类嗤?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤辨宠,失蹤者是張志新(化名)和其女友劉穎遗锣,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體彭羹,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡黄伊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了派殷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片还最。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡墓阀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拓轻,到底是詐尸還是另有隱情斯撮,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布扶叉,位于F島的核電站勿锅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏枣氧。R本人自食惡果不足惜溢十,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望达吞。 院中可真熱鬧张弛,春花似錦、人聲如沸酪劫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)覆糟。三九已至刻剥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滩字,已是汗流浹背造虏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踢械,地道東北人酗电。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像内列,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子背率,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. 委派模式 1.1 委派模式的簡(jiǎn)介 委派模式不屬于 GOF23 種設(shè)計(jì)模式中话瞧。 委派模式( Delegate ...
    AnonyStar閱讀 475評(píng)論 0 0
  • 委派模式(Delegate Pattern) 介紹:委派模式(Delegate Pattern)的基本作用就是負(fù)責(zé)...
    曾是少年_1478閱讀 254評(píng)論 0 0
  • 委派模式 委派模式不屬于GOF23種設(shè)計(jì)模式中。委派模式(DelegatePattern)的基本作用就是負(fù)責(zé)任務(wù)的...
    javacoo閱讀 239評(píng)論 0 1
  • 委派模式的定義及應(yīng)用場(chǎng)景 委派模式不屬于 GOF23 種設(shè)計(jì)模式中寝姿。委派模式(Delegate Pattern)的...
    提瑪歐斯閱讀 385評(píng)論 0 0
  • 表情是什么交排,我認(rèn)為表情就是表現(xiàn)出來(lái)的情緒。表情可以傳達(dá)很多信息饵筑。高興了當(dāng)然就笑了埃篓,難過(guò)就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,133評(píng)論 2 7