1. 程式人生 > >Java設計模式 模板方法(Template Method)

Java設計模式 模板方法(Template Method)

Book物件程式碼如下:

[java] view plaincopy
public class Book {  
  
    private String bookName;  
    private int pages;  
    private double price;  
    private String author;  
    private String isbn;  
    public String getBookName() {  
        return bookName;  
    }  
    public void setBookName(String bookName) {  
        this.bookName = bookName;  
    }  
    public int getPages() {  
        return pages;  
    }  
    public void setPages(int pages) {  
        this.pages = pages;  
    }  
    public double getPrice() {  
        return price;  
    }  
    public void setPrice(double price) {  
        this.price = price;  
    }  
    public String getAuthor() {  
        return author;  
    }  
    public void setAuthor(String author) {  
        this.author = author;  
    }  
    public String getIsbn() {  
        return isbn;  
    }  
    public void setIsbn(String isbn) {  
        this.isbn = isbn;  
    }  
}  

然後寫一個類專門用於將Book物件包裝成XML格式:

[java] view plaincopy
public class Formatter {  
    public String formatBook(Book book) {  
        System.out.println("format begins");  
        String result = "";  
        result += "<book_name>" + book.getBookName() + "</book_name>\n";  
        result += "<pages>" + book.getPages() + "</pages>\n";  
        result += "<price>" + book.getPrice() + "</price>\n";  
        result += "<author>" + book.getAuthor() + "</author>\n";  
        result += "<isbn>" + book.getIsbn() + "</isbn>\n";  
        System.out.println("format finished");  
        return result;  
    }  
}  

呼叫程式碼如下:

[java] view plaincopy
public class Test {  
    public static void main(String[] args) throws Exception {  
        Book book = new Book();  
        book.setBookName("Thinking in Java");  
        book.setPages(880);  
        book.setPrice(68);  
        book.setAuthor("Bruce Eckel");  
        book.setIsbn("9787111213826");  
        Formatter formatter = new Formatter();  
        String result = formatter.formatBook(book);  
        System.out.println(result);  
    }  
}  

你寫好了之後,迫不及待地開始執行,執行結果也完全符合你的期望。


專案經理看完後,對你非常滿意,小夥效率很高的嘛!你也非常的得意。

不過兩天之後,專案經理又找到了你,他說之前沒有考慮到需要互動的客戶端還包括手機裝置,而手機裝置都比較吃流量,用XML格式來傳輸太耗流量了,想最好能改成使用JSON格式傳輸。但是之前的XML格式也要保留,最好可以由客戶端指定使用哪種格式。

你有些不開心,心裡低估著,為什麼一開始不考慮周全呢,現在又要改遺留程式碼。但對方畢竟是領導,你還是要服從命令的,於是你開始修改Formatter類:

[java] view plaincopy
public class Formatter {  
  
    public static final int XML = 0;  
    public static final int JSON = 1;  
    public String formatBook(Book book, int format) {  
        System.out.println("format begins");  
        String result = "";  
        if (format == XML) {  
            result += "<book_name>" + book.getBookName() + "</book_name>\n";  
            result += "<pages>" + book.getPages() + "</pages>\n";  
            result += "<price>" + book.getPrice() + "</price>\n";  
            result += "<author>" + book.getAuthor() + "</author>\n";  
            result += "<isbn>" + book.getIsbn() + "</isbn>\n";  
        } else if (format == JSON) {  
            result += "{\n";  
            result += "\"book_name\" : \"" + book.getBookName() + "\",\n";  
            result += "\"pages\" : \"" + book.getPages() + "\",\n";  
            result += "\"price\" : \"" + book.getPrice() + "\",\n";  
            result += "\"author\" : \"" + book.getAuthor() + "\",\n";  
            result += "\"isbn\" : \"" + book.getIsbn() + "\",\n";  
            result += "}";  
        }  
        System.out.println("format finished");  
        return result;  
    }  
}  

呼叫程式碼如下:

[java] view plaincopy
public class Test {  
  
    public static void main(String[] args) throws Exception {  
        Book book = new Book();  
        book.setBookName("Thinking in Java");  
        book.setPages(880);  
        book.setPrice(68);  
        book.setAuthor("Bruce Eckel");  
        book.setIsbn("9787111213826");  
        Formatter formatter = new Formatter();  
        String result = formatter.formatBook(book, Formatter.XML);  
        System.out.println(result);  
        result = formatter.formatBook(book, Formatter.JSON);  
        System.out.println(result);  
    }  
  
}  

再次執行程式,得到了以下結果。


專案經理看到執行結果後開心地說:“太好了,這正是我想要的!” 

可是你這次卻沒有那麼開心,你覺得程式碼已經有些混亂了,XML格式的邏輯和JSON格式的邏輯混淆在一起,非常不利於閱讀,而且如果以後還需要擴充套件功能也會非常困難。好在傳輸格式一般也就XML和JSON了,應該不會再有什麼擴充套件了,你這樣安慰自己道。

但幻想總會被現實打破,“我最近聽說有個YAML格式挺好玩的.......” 專案經理說道。這個時候你已經有想打人的衝動了!!!

很多時候就是這樣,在公司裡寫的程式碼亂七八糟,質量極差,很大一部分原因就是因為需求變來變去。我們不斷在原有程式碼基礎上補充各種後續加入的情況,在一行行新增的if語句下面,我們的程式碼變得不堪入目。當然,我們作為程式設計師,對於需求這種東西沒有太多的話語權,在這方面我們無能為力。但是我們可以儘量地把程式的架構設計好,讓我們寫出的程式碼更具有擴充套件性,這樣就可以應對各種需求變更了。

下面你將要使用23種設計模式中的模板方法來改進以上程式。

首先將Formatter中的程式碼進行修改,如下所示:

[java] view plaincopy
public abstract class Formatter {  
  
    public String formatBook(Book book, int format) {  
        beforeFormat();  
        String result = formating(book);  
        afterFormat();  
        return result;  
    }  
    protected void beforeFormat() {  
        System.out.println("format begins");  
    }  
    protected abstract String formating(Book book);  
    protected void afterFormat() {  
        System.out.println("format finished");  
    }  
} 

你會發現format_book方法只有四步,第一步呼叫before_format,去列印格式轉換前的日誌。第二步呼叫formating,這個方法是個抽象方法,用於處理具體的轉換邏輯,因此每一個繼承自Formatter的子類都需要重寫此方法,來實現各自的轉換邏輯。第三步呼叫after_format,去列印格式轉換後的日誌。第四步返回result。由於類中存在了抽象方法,我們也就需要把Formatter宣告成抽象類。

然後要定義專門的子類來處理每種傳輸格式的具體邏輯,這樣不同傳輸格式的邏輯可以從一個方法裡分離開,明顯便於閱讀和理解。

定義類XMLFormatter繼承自Formatter,裡面加入處理XML格式的具體邏輯:

[java] view plaincopy
public class XMLFormatter extends Formatter {  
  
    @Override  
    protected String formating(Book book) {  
        String result = "";  
        result += "<book_name>" + book.getBookName() + "</book_name>\n";  
        result += "<pages>" + book.getPages() + "</pages>\n";  
        result += "<price>" + book.getPrice() + "</price>\n";  
        result += "<author>" + book.getAuthor() + "</author>\n";  
        result += "<isbn>" + book.getIsbn() + "</isbn>\n";  
        return result;  
    }  
}  

定義類JSONFormatter繼承自Formatter,裡面加入處理JSON格式的具體邏輯:

[java] view plaincopy
public class JSONFormatter extends Formatter {  
  
    @Override  
    protected String formating(Book book) {  
        String result = "";  
        result += "{\n";  
        result += "\"book_name\" : \"" + book.getBookName() + "\",\n";  
        result += "\"pages\" : \"" + book.getPages() + "\",\n";  
        result += "\"price\" : \"" + book.getPrice() + "\",\n";  
        result += "\"author\" : \"" + book.getAuthor() + "\",\n";  
        result += "\"isbn\" : \"" + book.getIsbn() + "\",\n";  
        result += "}";  
        return result;  
    }  
  
}  

最後呼叫程式碼如下:
[java] view plaincopy
public class Test {  
  
    public static void main(String[] args) throws Exception {  
        Book book = new Book();  
        book.setBookName("Thinking in Java");  
        book.setPages(880);  
        book.setPrice(68);  
        book.setAuthor("Bruce Eckel");  
        book.setIsbn("9787111213826");  
        XMLFormatter xmlFormatter = new XMLFormatter();  
        String result = xmlFormatter.formatBook(book);  
        System.out.println(result);  
        JSONFormatter jsonFormatter = new JSONFormatter();  
        result = jsonFormatter.formatBook(book);  
        System.out.println(result);  
    }  
  
}  
執行之後,你會發現執行結果和修改前程式碼的執行結果完全相同。但是使用模板方法之後,程式碼的可讀性有了很大的提高,因為處理格式轉換的程式碼都放到了各自的類當中,而不是全部塞進一個方法中。並且在擴充套件性上也有了很大的提升,比如你開始感興趣專案經理說的YAML格式了。

定義類YAMLFormatter繼承自Formatter,裡面加入處理YAML格式的具體邏輯:
[java] view plaincopy
public class YAMLFormatter extends Formatter {  
  
    @Override  
    protected String formating(Book book) {  
        String result = "";  
        result += "book_name: " + book.getBookName() + "\n";  
        result += "pages: " + book.getPages() + "\n";  
        result += "price: " + book.getPrice() + "\n";  
        result += "author: " + book.getAuthor() + "\n";  
        result += "isbn: " + book.getIsbn() + "\n";  
        return result;  
    }  
  
}  

呼叫程式碼只需要加入:
[java] view plaincopy
YAMLFormatter yamlFormatter = new YAMLFormatter();  
String result = yamlFormatter.formatBook(book);  
System.out.println(result);  

好了,令人頭疼的YAML格式就這樣被支援了,只需要在呼叫的時候決定是例項化XMLFormatter,JSONFormatter還是YAMLFormatter,就可以按照相應的規格進行格式轉換了。而且整體的程式碼很有條理,看起來也很舒心。這個時候,你會輕鬆地向專案經理調侃一句,還有需要支援的格式嗎?

模板方法: 定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。

相關推薦

Java設計模式 模板方法(Template Method)

Book物件程式碼如下: [java] view plaincopy public class Book { private String bookName; private int pages; private double

Java 設計模式--模板方法(Template Method)

在星巴茲咖啡有著嚴格的咖啡沖泡法和茶沖泡法,分別如下: 星巴茲咖啡沖泡法: 1. 把水煮沸 2. 用沸水沖泡咖啡 3. 把咖啡倒進杯子 4. 加糖和牛奶 星巴茲茶沖泡法 1. 把水煮沸 2. 用沸水浸泡茶葉 3. 把茶倒進杯子 4. 加檸檬

Java設計模式模板方法(Template Method)

模板是指在薄片塑料板上面寫字後挖空,再使用毛筆或色筆塗滿挖空部分,就能看到純手工而以不失工整的字樣,看到模板上的挖空形狀,馬上就知道最後會變出什麼樣子的字,不過實際上所顯現出來的字樣還是要依所使用的畫筆種類而定.拿黑色簽字筆當畫筆,結果當然就是簽字筆的字樣;當用鉛筆來畫,得到

設計模式-模板方法(Template Method)

概述 定義 : 定義了一個演算法的骨架, 並允許子類為一個或多個步驟提供實現 模板方法使得子類可以在不改變演算法結構的情況下, 重新定義演算法的某些步驟 型別 : 行為型 適用場景 一次性實現一個演算法的不變的部分, 並將可變的行為留給子類來

java設計模式----模板方法模式

抽象類 子類 底層 代碼 做事 方法 模板 期待 代碼復用 模板方法模式:   在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變算法結構的情況下,重新定義算法中的某些實現。 好萊塢原則:   別調用(打電話給)我們,我們會調用(打電話給

Java設計模式 - 模板方法模式

Java設計模式 - 模板方法模式 定義一個演算法的骨架,並將一些步驟通過子類表達。   UML圖示 要點 1. 定義一個演算法的骨架 - 建立一個抽象類 2. 將一些步驟通過子類表達 - 子類繼承抽象類 賦予不同實現   模板方法應用例項 模板方法

java設計模式--模板方法模式

1 簡介     定義一個模板結構,將具體內容延遲到子類去實現。它主要作用:在不改變模板結構的前提下在子類中重新定義模板中的內容。 主要兩點      1   提高程式碼複用性  &n

java設計模式--模板方法

1.模板方法定義 模板方法模式在一個方法中定義一個演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變演算法結構的情況下,重新定義演算法中的某些步驟。 2.模板方法的類圖 如圖,一個簡單的汽車例項。例項的程式碼如下: 定義一個汽車抽象模型的類。

Java設計模式模板方法模式

模板方法模式僅僅使用了Java的繼承機制,但它是一個應用非常廣泛的模式。1、定義:一個操作中的演算法的框架,而將一些步驟延遲到子類中。使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。

Java設計模式-模板方法模式

定義 Define the skeleton of an algorithm in an operation,defer

Java設計模式透析之 —— 模板方法(Template Method)

style 格式 XML nis 實現 rgs format) font 原因 轉載請註明出處:http://blog.csdn.net/guolin_blog/article/details/8744002 今天你還是像往常一樣來上班,一如既往地開始了你的編程工作。

Java設計模式模板方法(Template Method)

模式定義 需求背景 具體實現 模式定義 模板方法: 定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類可以不改變一個演算法的結構

Java設計模式之從[歡迎介面]分析模板方法(Template Method)模式

  模板方法是在抽象類中最常用的模式了(應該沒有之一),它定義一個操作中演算法的骨架,而將一些步驟延遲到子類中,使得子類可以不改變一個演算法的結構即可重新定義演算法的某些步驟。   例如我們要編寫一個歡迎介面,如果使用者是第一次開啟本軟體,則彈出一個歡迎的提示。為了能夠實現

Java設計模式之 —— 模板方法(Template Method)

今天你還是像往常一樣來上班,一如既往地開始了你的程式設計工作。 專案經理告訴你,今天想在伺服器端增加一個新功能,希望寫一個方法,能對Book物件進行處理,將Book物件的所有欄位以XML格式進行包裝,這樣以後可以方便與客戶端進行互動。並且在包裝開始前和結束後要列

設計模式模板方法(Template Method)

老板 就是 iam pre 一起 完成 nbsp str 記錄學習   在整理模板方法之前,先來說點廢話吧。除了記錄學習總結,也來記錄一下生活吧。   我們公司的老板在北京,老板也會因為項目來公司,不過不是天天來。公司有個同事,只要老板不在就天天遲到,而且一天比一天晚,經常

設計模式19:Template Method Pattern (模板方法模式)

Define:Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine c

設計模式——模板方法模式Template Method

一個抽象類中,有一個主方法,再定義1...n個方法,可以是抽象的,也可以是實際的方法,定義一個類,繼承該抽象類,重寫抽象方法,通過呼叫抽象類,實現對子類的呼叫 就是在AbstractCalculator類中定義一個主方法

設計模式模板方法Template Method

在基類中定義一套演算法框架,子類只能更改特定的實現細節。 程式碼示例: class AbstractClass { public: void templateMethod() { func

C++設計模式——模板方法Template Method

模板方法(template method)設計模式用於定義一個包含許多步驟的演算法框架,允許子類重寫(覆蓋)演算法的某一個步驟而不改變演算法整體的流程和框架。 模板方法提供的流程是骨架,子類無須覆蓋模板方法本身,只需繼承即可,即模板方法無須是 virtu

設計模式——模板方法模式Template Method Pattern】

 我先設計個類圖: 非常簡單的實現,你要悍馬模型,我就給你悍馬模型,先寫個抽象類,然後兩個不同型號的模型實現類,那我們把這個程式實現出來: HummerModel抽象類的程式清單如下: package template.method.pattern; /** * 是