5.設(shè)計模式-模板模式霎烙、適配模式

模板方法模式(Template Method Pattern)

  • 介紹:模板模式通常又叫模板方法模式(Template Method Pattern)是指定義一個算法的骨架官疲,并允許子類為一個或者 多個步驟提供實現(xiàn)
    模板方法使得子類可以在不改變算法結(jié)構(gòu)的情況下拙已,重新定義 算法的某些步驟淫茵。
    屬于行為性設(shè)計模式
  • 使用場景
    1. 一次性實現(xiàn)一個算法的不變的部分,并將可變的行為留給 子類來實現(xiàn)页眯。
    2. 各子類中公共的行為被提取出來并集中到一個公共的父類 中梯捕,從而避免代碼重復。
  • 優(yōu)點:
    1. 提高代碼的復用性窝撵。
    2. 提高代碼的擴展性傀顾。
    3. 符合開閉原則。
  • 缺點:
    1. 類數(shù)目的增加碌奉。
    2. 間接地增加了系統(tǒng)實現(xiàn)的復雜度
    3. 繼承關(guān)系自身缺點短曾,如果父類添加新的抽象方法,所有子 類都要改一遍
//mvn依賴
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.1</version>
</dependency>


// 以jdbc 的數(shù)據(jù)庫連接為例
/**
 * ORM映射定制化的接口
 */
public interface RowMapper<T> {
    T mapRow(ResultSet rs,int rowNum) throws Exception;
}

//模板
public abstract class JdbcTemplate {
    private DataSource dataSource;

    public JdbcTemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public List<?> executeQuery(String sql, RowMapper<?> rowMapper, Object[] values){
        //TODO  以下方法子類集成使用的 ,若不允許子類修改赐劣,可以添加fianl關(guān)鍵字
        try {
            //1嫉拐、獲取連接
            Connection conn = this.getConnection();
            //2、創(chuàng)建語句集
            PreparedStatement pstm = this.createPrepareStatement(conn,sql);
            //3隆豹、執(zhí)行語句集
            ResultSet rs = this.executeQuery(pstm,values);
            //4椭岩、處理結(jié)果集
            List<?> result = this.paresResultSet(rs,rowMapper);
            //5、關(guān)閉結(jié)果集
            this.closeResultSet(rs);
            //6璃赡、關(guān)閉語句集
            this.closeStatement(pstm);
            //7判哥、關(guān)閉連接
            this.closeConnection(conn);
            return result;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    protected void closeConnection(Connection conn) throws Exception {
        //數(shù)據(jù)庫連接池,我們不是關(guān)閉
        conn.close();
    }

    protected void closeStatement(PreparedStatement pstm) throws Exception {
        pstm.close();
    }

    protected void closeResultSet(ResultSet rs) throws Exception {
        rs.close();
    }

    protected List<?> paresResultSet(ResultSet rs, RowMapper<?> rowMapper) throws Exception {
        List<Object> result = new ArrayList<Object>();
        int rowNum = 1;
        while (rs.next()){
            result.add(rowMapper.mapRow(rs,rowNum ++));
        }
        return result;
    }

    protected ResultSet executeQuery(PreparedStatement pstm, Object[] values) throws Exception {
        for (int i = 0; i < values.length; i++) {
            pstm.setObject(i,values[i]);
        }
        return pstm.executeQuery();
    }

    protected PreparedStatement createPrepareStatement(Connection conn, String sql) throws Exception {
        return conn.prepareStatement(sql);
    }

    public Connection getConnection() throws Exception {
        return this.dataSource.getConnection();
    }
}

//entity
public class User  {
    private String uid;
    private String username;
    private int age;
    private String addr;
    // setget() 
}


//Dao
public class UserDao extends JdbcTemplate {
    public UserDao(DataSource dataSource) {
        super(dataSource);
    }

    public List<?> selectAll(){
        String sql = "select * from t_user";
        return super.executeQuery(sql, new RowMapper<User>() {
            public User mapRow(ResultSet rs, int rowNum) throws Exception {
                User member = new User();
                //字段過多碉考,可使用原型模式
                member.setUid(rs.getString("uid"));
                member.setUsername(rs.getString("username"));
                member.setAge(rs.getInt("age"));
                member.setAddr(rs.getString("addr"));
                return member;
            }
        },null);
    }
}





適配器模式(Adapter Pattern)

  • 介紹:適配器模式(Adapter Pattern)是指將一個類的接口轉(zhuǎn)換成 客戶期望的另一個接口塌计,使原本的接口不兼容的類可以一起工作
    屬于結(jié)構(gòu)型設(shè)計模式。
  • 使用場景
    1. 已經(jīng)存在的類侯谁,它的方法和需求不匹配(方法結(jié)果相同或相似) 的情況锌仅。
    2. 適配器模式不是軟件設(shè)計階段考慮的設(shè)計模式章钾,是隨著軟件維護, 由于不同產(chǎn)品热芹、不同廠家造成功能類似而接口不相同情況下的解決 方案
  • 優(yōu)點:
    1. 能提高類的透明性和復用贱傀,現(xiàn)有的類復用但不需要改變。
    2. 目標類和適配器類解耦伊脓,提高程序的擴展性府寒。
    3. 在很多業(yè)務(wù)場景中符合開閉原則。
  • 缺點:
    1. 適配器編寫過程需要全面考慮报腔,可能會增加系統(tǒng)的復雜性
    2. 增加代碼閱讀難度株搔,降低代碼可讀性,過多使用適配器會使系統(tǒng) 代碼變得凌亂
//以用戶登錄為例, 賬號密碼登錄,qq登錄纯蛾,微信登錄等 (策略  纤房、工廠、適配器)
//entity
public class User {

    private String username;
    private String password;
    private String mid;
    private String info;

    //setget()  ...
}

//result Entity
public class ResultMsg {

    private int code;
    private String msg;
    private Object data;
    
    //setget()  ...
}


//adapter
/**
 * 在適配器里面翻诉,這個接口是可有可無炮姨,不要跟模板模式混淆
 * 模板模式一定是抽象類,而這里僅僅只是一個接口
 * Created by Tom on 2019/3/16.
 */
public interface LoginAdapter {
    boolean support(Object adapter);
    ResultMsg login(String id,Object adapter);

}

//qq 登錄
public class LoginForQQAdapter implements LoginAdapter {
    public boolean support(Object adapter) {
        return adapter instanceof LoginForQQAdapter;
    }

    public ResultMsg login(String id, Object adapter) {
        return ew ResultMsg(200,"登錄成功",id + ": 恭喜登錄成功");;
    }
}

// 微信登錄
public class LoginForWechatAdapter implements LoginAdapter {
    public boolean support(Object adapter) {
        return adapter instanceof LoginForWechatAdapter;
    }
    public ResultMsg login(String id, Object adapter) {
        return null;
    }
}

//其他登錄方式  token碰煌、微博等等
 ......
 
 
// 登錄方法
public class SiginService {

    /**
     * 注冊方法
     * @param username
     * @param password
     * @return
     */
    public ResultMsg regist(String username,String password){
        return  new ResultMsg(200,"注冊成功",new Member());
    }


    /**
     * 登錄的方法
     * @param username
     * @param password
     * @return
     */
    public ResultMsg login(String username,String password){
        return new ResultMsg(200,"登錄成功",username + ": 恭喜登錄成功");
    }

}


/**
 * 只擴展
 */
public interface IPassportForThird {

    /**
     * QQ登錄
     * @param id
     * @return
     */
    ResultMsg loginForQQ(String id);

    /**
     * 微信登錄
     * @param id
     * @return
     */
    ResultMsg loginForWechat(String id);

    /**
     * 記住登錄狀態(tài)后自動登錄
     * @param token
     * @return
     */
    ResultMsg loginForToken(String token);

    /**
     * 手機號登錄
     * @param telphone
     * @param code
     * @return
     */
    ResultMsg loginForTelphone(String telphone, String code);

    /**
     * 注冊后自動登錄
     * @param username
     * @param passport
     * @return
     */
    ResultMsg loginForRegist(String username, String passport);
}



//結(jié)合策略模式剑令、工廠模式、適配器模式
public class PassportForThirdAdapter extends SiginService implements IPassportForThird {

    public ResultMsg loginForQQ(String id) {
//        return processLogin(id,RegistForQQAdapter.class);
        return processLogin(id,LoginForQQAdapter.class);
    }

    public ResultMsg loginForWechat(String id) {
        return processLogin(id,LoginForWechatAdapter.class);
    }

    public ResultMsg loginForToken(String token) {
        return processLogin(token,LoginForTokenAdapter.class);
    }

    public ResultMsg loginForTelphone(String telphone, String code) {
        return processLogin(telphone,LoginForTelAdapter.class);
    }

    public ResultMsg loginForRegist(String username, String passport) {
        super.regist(username,passport);
        return super.login(username,passport);
    }

    
    private ResultMsg processLogin(String key,Class<? extends LoginAdapter> clazz){
        try{
            //適配器不一定要實現(xiàn)接口
            LoginAdapter adapter = clazz.newInstance();

            //判斷傳過來的適配器是否能處理指定的邏輯
            if(adapter.support(adapter)){
                return adapter.login(key,adapter);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
  
}


// 客戶端調(diào)用
  public static void main(String[] args) {

        IPassportForThird passportForThird = new PassportForThirdAdapter();

        passportForThird.loginForQQ("");


    }





?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拄查,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子棚蓄,更是在濱河造成了極大的恐慌堕扶,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梭依,死亡現(xiàn)場離奇詭異稍算,居然都是意外死亡,警方通過查閱死者的電腦和手機役拴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門糊探,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人河闰,你說我怎么就攤上這事科平。” “怎么了姜性?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵瞪慧,是天一觀的道長。 經(jīng)常有香客問我部念,道長弃酌,這世上最難降的妖魔是什么氨菇? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮妓湘,結(jié)果婚禮上查蓉,老公的妹妹穿的比我還像新娘。我一直安慰自己榜贴,他們只是感情好豌研,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著竣灌,像睡著了一般聂沙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上初嘹,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天及汉,我揣著相機與錄音,去河邊找鬼屯烦。 笑死坷随,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的驻龟。 我是一名探鬼主播温眉,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼翁狐!你這毒婦竟也來了类溢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤露懒,失蹤者是張志新(化名)和其女友劉穎闯冷,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懈词,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡蛇耀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了坎弯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纺涤。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖抠忘,靈堂內(nèi)的尸體忽然破棺而出撩炊,到底是詐尸還是另有隱情,我是刑警寧澤褐桌,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布衰抑,位于F島的核電站,受9級特大地震影響荧嵌,放射性物質(zhì)發(fā)生泄漏呛踊。R本人自食惡果不足惜砾淌,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谭网。 院中可真熱鬧汪厨,春花似錦、人聲如沸愉择。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锥涕。三九已至衷戈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間层坠,已是汗流浹背殖妇。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留破花,地道東北人谦趣。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像座每,于是被迫代替她去往敵國和親前鹅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

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