模板方法模式
模板模式通常又叫模板方法模式(Template Method Pattern)是指定義一個算法的骨架,並允許子類爲一個或者多個步驟提供實現。模板方法使得子類可以在不改變算法結構的情況下,重新定義算法的某些步驟,屬於行爲性設計模式。模板方法適用於以下應
用場景:
1、一次性實現一個算法的不變的部分,並將可變的行爲留給子類來實現。
2、各子類中公共的行爲被提取出來並集中到一個公共的父類中,從而避免代碼重複。
利用模板模式重構 JDBC 操作業務場景
創建一個模板類 JdbcTemplate,封裝所有的 JDBC 操作。以查詢爲例,每次查詢的表不同,返回的數據結構也就不一樣。我們針對不同的數據,都要封裝成不同的實體對象。而每個實體封裝的邏輯都是不一樣的,但封裝前和封裝後的處理流程是不變的,因此,我們可以使用模板方法模式來設計這樣的業務場景。
1)先創建約束 ORM 邏輯的接口RowMapper:
/**
* ORM映射定製化的接口
*/
public interface RowMapper<T> {
T mapRow(ResultSet rs,int rowNum) throws Exception;
}
2)再創建封裝了所有處理流程的抽象類 JdbcTemplate:
public abstract class JdbcTemplate {
private DataSource dataSource;
public JdbcTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
public List<?> executeQuery(String sql, RowMapper<?> rowMapper, Object[] values){
try {
//1、獲取連接
Connection conn = this.getConnection();
//2、創建語句集
PreparedStatement pstm = this.createPrepareStatement(conn,sql);
//3、執行語句集
ResultSet rs = this.executeQuery(pstm,values);
//4、處理結果集
List<?> result = this.paresResultSet(rs,rowMapper);
//5、關閉結果集
this.closeResultSet(rs);
//6、關閉語句集
this.closeStatement(pstm);
//7、關閉連接
this.closeConnection(conn);
return result;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
protected void closeConnection(Connection conn) throws Exception {
//數據庫連接池,我們不是關閉
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();
}
}
3)創建實體對象 Member 類:
public class Member {
private String username;
private String password;
private String nickname;
private int age;
private String addr;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
}
4)創建數據庫操作類 MemberDao:
public class MemberDao extends JdbcTemplate {
public MemberDao(DataSource dataSource) {
super(dataSource);
}
public List<?> selectAll(){
String sql = "select * from t_member";
return super.executeQuery(sql, new RowMapper<Member>() {
public Member mapRow(ResultSet rs, int rowNum) throws Exception {
Member member = new Member();
//字段過多,原型模式
member.setUsername(rs.getString("username"));
member.setPassword(rs.getString("password"));
member.setAge(rs.getInt("age"));
member.setAddr(rs.getString("addr"));
return member;
}
},null);
}
}
5)客戶端測試代碼:
public class MemberDaoTest {
public static void main(String[] args) {
MemberDao memberDao = new MemberDao(null);
List<?> result = memberDao.selectAll();
System.out.println(result);
}
}
當然我們是沒有鏈接的跑不起來的。
6)模板模式的優缺點
優點:
1、利用模板方法將相同處理邏輯的代碼放到抽象父類中,可以提高代碼的複用性。
2、將不同的代碼不同的子類中,通過對子類的擴展增加新的行爲,提高代碼的擴展性。
3、把不變的行爲寫在父類上,去除子類的重複代碼,提供了一個很好的代碼複用平臺,
符合開閉原則。
缺點:
1、類數目的增加,每一個抽象類都需要一個子類來實現,這樣導致類的個數增加。
2、類數量的增加,間接地增加了系統實現的複雜度。
3、繼承關係自身缺點,如果父類添加新的抽象方法,所有子類都要改一遍。
模板方法模式比較簡單,相信小夥伴們肯定能學會,也肯定能理解好!只要勤加練習,多結合業務場景思考問題,就能夠把模板方法模式運用好。
適配器模式
適配器模式的應用場景
適配器模式(Adapter Pattern)是指將一個類的接口轉換成客戶期望的另一個接口,使原本的接口不兼容的類可以一起工作,屬於結構型設計模式。
適配器適用於以下幾種業務場景:
1、已經存在的類,它的方法和需求不匹配(方法結果相同或相似)的情況。
2、適配器模式不是軟件設計階段考慮的設計模式,是隨着軟件維護,由於不同產品、不同廠家造成功能類似而接口不相同情況下的解決方案。有點亡羊補牢的感覺。
生活中也非常的應用場景,例如電源插轉換頭、手機充電轉換頭、顯示器轉接頭。
在中國民用電都是 220V 交流電,但我們手機使用的鋰電池使用的 5V 直流電。因此,我們給手機充電時就需要使用電源適配器來進行轉換。下面我們用代碼來還原這個生活場景。
1)創建 AC220 類,表示 220V 交流電:
public class AC220 {
public int outputAC220V(){
int output = 220;
System.out.println("輸出電流" + output + "V");
return output;
}
}
2)創建 DC5 接口,表示 5V 直流電的標準:
public interface DC5 {
int outoupDC5V();
}
3)創建電源適配器 PowerAdapter 類:
public class PowerAdapter implements DC5 {
private AC220 ac220;
public PowerAdapter(AC220 ac220) {
this.ac220 = ac220;
}
public int outoupDC5V() {
int adapterInput = ac220.outputAC220V();
int adapterOutput = adapterInput / 44;
System.out.println("使用PowerAdapter輸入AC:" + adapterInput + "V,輸出DC:" + adapterOutput + "V");
return adapterOutput;
}
}
4)測試類
public class PowerAdapterTest {
public static void main(String[] args) {
DC5 dc5 = new PowerAdapter(new AC220());
dc5.outoupDC5V();
}
}
5)結果截圖
6)適配器模式的優缺點
優點:
1、能提高類的透明性和複用,現有的類複用但不需要改變。
2、目標類和適配器類解耦,提高程序的擴展性。
3、在很多業務場景中符合開閉原則。
缺點:
1、適配器編寫過程需要全面考慮,可能會增加系統的複雜性。
2、增加代碼閱讀難度,降低代碼可讀性,過多使用適配器會使系統代碼變得凌亂。