<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          淺談Java常見設(shè)計(jì)模式(六)

          共 7854字,需瀏覽 16分鐘

           ·

          2021-05-19 13:28

          對(duì)這個(gè)世界如果你有太多的抱怨

          跌倒了就不敢繼續(xù)往前走

          為什么人要這么的脆弱墮落

          請(qǐng)你打開電視看看

          多少人為生命在努力勇敢的走下去

          我們是不是該知足

          珍惜一切就算沒(méi)有擁有



          很久沒(méi)有回顧過(guò)jdbc操作了,今天回顧下原生Java操作數(shù)據(jù)庫(kù)的流程,


          1、首先載入數(shù)據(jù)庫(kù)驅(qū)動(dòng)


          2、獲取數(shù)據(jù)庫(kù)連接


          3、獲取PreparedStatement


          4、執(zhí)行sql語(yǔ)句


          5、處理結(jié)果集


          6、關(guān)閉連接和PreparedStatement、ResultSet


          那么對(duì)于查詢的話,通常來(lái)說(shuō),1.2.3.4這幾個(gè)步奏是肯定一致的,第5步,結(jié)果集處理,每個(gè)查詢的結(jié)果集處理可能是太一樣的,所以是一個(gè)可微調(diào)的因素。


          那么基于此,來(lái)嘗試進(jìn)行一次原生的jdbc操作,平常ORM框架用多了,這里來(lái)熟悉一些底層一點(diǎn)的東西。


          下面例子使用的數(shù)據(jù)庫(kù)是Mysql8.0.11


          首先有一個(gè)實(shí)體類,用于一個(gè)查詢結(jié)果的封裝:


          29f19690ae9a3942ecb2dcc134429dff.webp


          這里僅列舉了幾個(gè)字段,意思一下就好



          下面定義一個(gè)RowMapper結(jié)果集映射器接口,擁有一個(gè)結(jié)果封裝的方法


          package?com.lgli.behavior.template.jdbc;import?java.sql.ResultSet;/** * 結(jié)果集處理接口 * @author lgli?*/public?interface?RowMapper<T>?{????T?mapRow(ResultSet?resultSet)?throws?Exception;}


          下面定義一個(gè)jdbc操作類,因?yàn)橐陨蠋讉€(gè)操作步驟,除了某些細(xì)節(jié)有些許變化之外,大體上都是一致的,那么這里設(shè)計(jì)了一個(gè)類,具有操作數(shù)據(jù)庫(kù)的標(biāo)準(zhǔn)步驟方法,同時(shí),通過(guò)結(jié)果集處理接口RowMapper的具體實(shí)現(xiàn)類來(lái)實(shí)現(xiàn)對(duì)細(xì)節(jié)的微調(diào)。那么這個(gè)類,簡(jiǎn)單稱為JdbcTemplate類:


          package com.lgli.behavior.template.jdbc;
          import java.sql.*;import java.util.ArrayList;import java.util.List;
          /** * jdbc操作模板 * @author lgli */public abstract class JdbcTemplate {
          /** * mysql數(shù)據(jù)驅(qū)動(dòng) */ private static final String DATA_SOURCE_DRIVER = "com.mysql.cj.jdbc.Driver";
          /** * 數(shù)據(jù)庫(kù)連接地址 */ private static final String DATA_SOURCE_URL = "jdbc:mysql://localhost:3306/xttl?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT&useSSL=false";
          /** * 用戶名 */ private static final String USER = "root";
          /** * 密碼 */ private static final String PASSWORD = "soft01";


          public <T> List<T> executeQuery(String sql,RowMapper<T> rowMapper){ try{ //1、載入數(shù)據(jù)庫(kù)驅(qū)動(dòng) initDataSourceDriver(); //2、獲取數(shù)據(jù)庫(kù)連接 Connection connection = getConnection(); //3、獲取PreparedStatement PreparedStatement preparedStatement = getPreparedStatement(sql,connection); //4、執(zhí)行sql語(yǔ)句 ResultSet resultSet = preparedStatement.executeQuery(); //5、處理結(jié)果集 List<T> result = dealResult(resultSet,rowMapper); //6、關(guān)閉連接和PreparedStatement close(connection,preparedStatement,resultSet); return result; }catch (Exception e){ e.printStackTrace(); }
          return null; }
          protected <T> List<T> dealResult(ResultSet resultSet, RowMapper<T> rowMapper) throws Exception{ List<T> result = new ArrayList<>(); while(resultSet.next()){ result.add(rowMapper.mapRow(resultSet)); } return result; }
          protected void close(Connection connection, PreparedStatement preparedStatement,ResultSet resultSet) throws Exception{ if(connection != null){ connection.close(); } if(preparedStatement != null){ preparedStatement.close(); }
          if(resultSet != null){ resultSet.close(); } }
          protected PreparedStatement getPreparedStatement(String sql,Connection connection) throws Exception { return connection.prepareStatement(sql); }
          private Connection getConnection() throws Exception{ return DriverManager.getConnection(DATA_SOURCE_URL,USER,PASSWORD); }
          private void initDataSourceDriver() throws Exception{ this.getClass().getClassLoader().loadClass(DATA_SOURCE_DRIVER);????}}


          這里我們簡(jiǎn)單用一個(gè)查詢舉例,其他的數(shù)據(jù)庫(kù)操作雷同


          可以看到,標(biāo)準(zhǔn)的步驟都是一樣的,每個(gè)數(shù)據(jù)庫(kù)操作都是這么來(lái)的,唯一不一樣的,就是結(jié)果集的處理。


          下面定義一個(gè)Dao,繼承自這個(gè)JdbcTemplate類:


          package com.lgli.behavior.template.jdbc;
          import java.util.List;
          /** * dao * @author lgli */public class Dao extends JdbcTemplate{
          public List<User> selectUser(){ String sql = "select * from user_basic_info"; return super.executeQuery(sql, resultSet -> { User user = new User(); user.setUserName(resultSet.getString("USER_NAME")); user.setUserUniqueSign(resultSet.getString("USER_UNIQUE_SIGN")); user.setUserPassword(resultSet.getString("USER_PASSWORD")); return user; });????}}


          這里定義一個(gè)查詢方法,調(diào)用模板類的executeQuery方法,傳入一個(gè)RowMapper的實(shí)現(xiàn)類,這里即是對(duì)查詢結(jié)果的封裝,每一個(gè)查詢的封裝可能存在差異,比如這里是查詢user_basic_info,假設(shè)查詢另外的表,其結(jié)果封裝肯定就是不一樣的了,這里主要利用鉤子方法實(shí)現(xiàn)對(duì)結(jié)果的自定義封裝。



          然后是我們的測(cè)試類:


          package?com.lgli.behavior.template.jdbc;import java.util.List;
          /** * test * @author lgli */public class DaoTest {
          public static void main(String[] args) { Dao dao = new Dao(); List<User> users = dao.selectUser(); for (User user : users) { System.out.println(user.toString()); } }}


          測(cè)試類直接調(diào)用查詢方法,打印結(jié)果:


          28faade761809c7d7d517b34ecebc28f.webp


          上面主要類JdbcTemplate類,我們稱為模板類,這種設(shè)計(jì)模式,稱為模板模式,即:一個(gè)抽象類公開定義了執(zhí)行它的方法的方式/模板。它的子類可以按需要重寫方法實(shí)現(xiàn),但調(diào)用將以抽象類中定義的方式進(jìn)行。


          假定下面這個(gè)業(yè)務(wù)場(chǎng)景:在系統(tǒng)已經(jīng)存在上面例子中的Dao類,這個(gè)

          selectUser也已經(jīng)成熟運(yùn)行了很久了,

          與此同時(shí),系統(tǒng)中有一個(gè)對(duì)人員處理的方法,


          package?com.lgli.construct.adapter;import java.util.List;
          /** * 人員處理類型 * @author lgli */public?class?OtherUserDeal?{ private List<OtherUser> dealUser(List<OtherUser> users){ for(OtherUser user : users){ user.setPassword("******"); } return users;????}}


          這個(gè)處理類,是專門對(duì)OtherUser進(jìn)行的處理,這個(gè)地方的這個(gè)OtherUser和前面的User類是不一樣的對(duì)象。


          這個(gè)時(shí)候,新的需求來(lái)了,需要利用OtherUserDeal?對(duì)上面例子中的查詢結(jié)果進(jìn)行處理。



          此時(shí),是可以單獨(dú)寫個(gè)方法來(lái)進(jìn)行操作的,那么如果在兩個(gè)方法業(yè)務(wù)邏輯很復(fù)雜的情況下,顯然,從頭開始來(lái)捋代碼邏輯時(shí)一個(gè)不明智的選擇,同時(shí)可能出現(xiàn)其他的BUG。


          這個(gè)時(shí)候,可以選擇新加入一個(gè)適配器類,讓這個(gè)適配器可以將這兩個(gè)毫無(wú)相關(guān)的方法(接口)建立一個(gè)橋梁,來(lái)解決這個(gè)問(wèn)題。


          這里新建一個(gè)Adapter類:


          package com.lgli.construct.adapter;
          import com.lgli.behavior.template.jdbc.Dao;import com.lgli.behavior.template.jdbc.User;
          import java.util.ArrayList;import java.util.List;

          /** * 適配器類 * @author lgli */public class Adapter extends Dao {
          private OtherUserDeal userDeal;
          public Adapter(OtherUserDeal userDeal) { this.userDeal = userDeal; }
          public List<OtherUser> dealWithUser(){ List<User> users = super.selectUser(); List<OtherUser> otherUsers = new ArrayList<>(); for(User user : users){ OtherUser otherUser = new OtherUser(); otherUser.setPassword(user.getUserPassword()); otherUser.setName(user.getUserName()); otherUser.setUserAccount(user.getUserUniqueSign()); otherUsers.add(otherUser); } return userDeal.dealUser(otherUsers);????}}


          一般來(lái)說(shuō),在實(shí)際的工作中,還是有一個(gè)比較標(biāo)準(zhǔn)的適配器模式,這里僅僅做個(gè)演示說(shuō)明,其代碼結(jié)構(gòu)存在較多的可以改造的地方,就不在這兒優(yōu)化了。


          package?com.lgli.construct.adapter;import java.util.List;

          /** * 適配器測(cè)試類 * @author lgli */public?class?AdapterTest?{ public static void main(String[] args) { Adapter adaper = new Adapter(new OtherUserDeal()); List<OtherUser> otherUsers = adaper.dealWithUser(); for(OtherUser user : otherUsers){ System.out.println(user); } }}


          這里一個(gè)簡(jiǎn)單的測(cè)試類,輸出結(jié)果:


          86c701628f1ac7d813e734a5a738d70f.webp



          這里,我們的適配器類,將兩個(gè)毫無(wú)相干的方法,結(jié)合起來(lái)了:


          看下類圖:


          ce830d6eaa567cdd7f7ad66234c80406.webp


          這里就比較粗超的描述了適配器和方法的基本關(guān)系,其實(shí)也就是一個(gè)簡(jiǎn)單的適配器的實(shí)現(xiàn),下面描述一個(gè)標(biāo)準(zhǔn)一些的場(chǎng)景:



          假定有一個(gè)播放器及其播放器實(shí)現(xiàn),這個(gè)播放器只能播放Mp3的音樂(lè):


          MediaPlay:


          package?com.lgli.construct.adapter;/** * 媒體播放器接口 * @author lgli */public?interface?MediaPlay?{????void?play();}


          播放器實(shí)現(xiàn)MediaPlayImpl,只能播放MP3:


          package com.lgli.construct.adapter;/** * 媒體播放器實(shí)現(xiàn) * @author lgli */public?class?MediaPlayImpl?implements?MediaPlay{    @Override    public void play() {        System.out.println("播放MP3!!!");    }}


          這個(gè)時(shí)候,忽然項(xiàng)目引進(jìn)了一個(gè)高級(jí)一點(diǎn)的播放器接口和實(shí)現(xiàn):


          高級(jí)播放器接口AdvancedMediaPlay


          package com.lgli.construct.adapter;/** * 高級(jí)播放器 * @author lgli */public interface AdvancedMediaPlay {
          void play();}


          高級(jí)播放器接口的其中一個(gè)實(shí)現(xiàn)AdvancedMediaPlayImpl,可以播放MP4文件:


          package com.lgli.construct.adapter;
          /** * 高級(jí)播放器實(shí)現(xiàn) * @author lgli */public class AdvancedMediaPlayImpl implements AdvancedMediaPlay{ @Override public void play() { System.out.println("播放MP4!!!"); }}


          這時(shí)候,有一個(gè)需求,需要用只能播放MP3的MediaPlayImpl去播放MP4,怎么辦?此時(shí)最好的解決方案就是,寫一個(gè)適配器,來(lái)關(guān)聯(lián)這兩個(gè)實(shí)現(xiàn):



          package com.lgli.construct.adapter;

          /** * 播放器適配器 * @author lgli */public?class?MediaPlayAdapter?{????public?void?play(String?type){ if(type.contains(".Mp3")){ new MediaPlayImpl().play(); }else if(type.contains(".Mp4")){ new AdvancedMediaPlayImpl().play(); }else{ System.out.println("can not play media"); }????}}


          寫個(gè)測(cè)試類:


          e0f8e45570fcdf404513fbd8a1f5d0c8.webp


          看下類圖:


          bb5e39847d652edcb599c21b18350893.webp


          這里的播放器適配器,將2個(gè)毫無(wú)關(guān)系的方法實(shí)現(xiàn)關(guān)聯(lián)起來(lái)了,這也是簡(jiǎn)單的適配器實(shí)現(xiàn)。






          點(diǎn)擊下面公眾號(hào)關(guān)注獲取更多。。。


          歡迎關(guān)注點(diǎn)贊轉(zhuǎn)發(fā),謝謝

          瀏覽 130
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人av久 | 日日干夜夜拍 | 黄色成人观看网站 | 做爰又粗又大又黄又硬 | 想要xx在线播放 |