軟件設計模式指南 創新設計模式:原型

設計模式第5部分

軟件設計模式指南 創新設計模式:原型

Photo by Alex wong on Unsplash

原型模式是通過克隆現有實例來創建新對象時使用的五個創建模式之一。

用簡單的英語來說,這僅表示您不使用new關鍵字來創建新實例,而是對現有對象進行了深克隆。 使用此模式有幾個原因,但最重要的一個方法是避免在某些應用程序中以標準方式創建新對象的昂貴成本,例如,使用" new"關鍵字。

某些應用程序從數據源加載數據,它可以是數據庫,文件等中的任何數據……如果您的應用程序需要加載數據,則每次創建新對象時加載相同的信息可能既費時又費力。 密集取決於大小。 這就是原型模式派上用場的地方。

例如,您的任務是設計和實施一個創建Staff的程序包。 工作人員包括教授,助理,保管人,實習生等……您的工作人員對象必須能夠返回所有工作人員的姓名,並按姓名進行查找。 我們假設數據源中的所有名稱都是唯一的。 現在想象一下,每次創建新對象時都必須打電話來加載工作人員的數據。 那可能是相當昂貴的操作。 我們可以使用原型模式來解決這個問題。

為了使對象可克隆,它需要實現Cloneable接口。 我們需要重寫clone方法以對要克隆的對象執行深層複製。 如果您不熟悉克隆概念,建議您查看"淺拷貝與深拷貝"之間的區別。

我們不會從示例中的數據源中讀取數據,而是為了簡潔起見,我們將對一些值進行硬編碼。 Staff類的代碼如下所示。

<code>public class Staff implements Cloneable {    private List<string> staffNames;public Staff(){        this.staffNames = new ArrayList<>();        loadStaffNames();    }//simulates a database call to get all staff names    private void loadStaffNames(){        this.staffNames.add("Michael Bublé");        this.staffNames.add("Frank Sinatra");        this.staffNames.add("Mile Davis");        this.staffNames.add("Louis Armstrong");        this.staffNames.add("Nat King Cole");    }    public List<string> getStaffNames(){        return this.staffNames;    }        public String findStaffByName(String name){        return this.staffNames                .stream()                .filter(x -> x.equalsIgnoreCase(name))                .findFirst()                .orElse(null);    }    @Override    public Object clone() throws CloneNotSupportedException{        Staff copiedStaff = (Staff)super.clone();        this.staffNames.stream().forEach(                x -> copiedStaff.staffNames.add(x));        return copiedStaff;    }}/<string>/<string>/<code>


在此Staff類中,昂貴的操作在loadStaffNames方法中執行,該方法是一個私有方法,每次使用new關鍵字創建對象時都會調用該方法。 因此,如果需要使用相同的數據創建對象,則無需再次重新加載數據。 該模式提供了一種通過克隆現有對象來創建實例的方法。

在findStaffByName方法中,我們還使用相同的加載數據執行搜索。 如果您的應用程序需要一種從數據庫或正在使用的數據源重新加載數據的方法,則您的類可以提供一種方法來執行此操作。

您仍然需要使用new關鍵字創建至少一個對象。 克隆某些對象意味著存在原始對象或現有對象。 一旦有了一個現有的對象,就可以在需要一個類的另一個實例時克隆它,而不必從頭開始創建一個新的實例。 您想要這樣做,是因為在我們的案例中,創建一個新數據庫將再次調用數據庫-或您試圖限制的任何昂貴操作。

然後,您可以使用Staff類,克隆就是這樣。

<code>public static void main(String[] args)  {    try {        Staff staff = new Staff();        System.out.println("number of staff in: "                    + staff.getStaffNames().size());        Staff copiedStaff = (Staff)staff.clone();        System.out.println("number of staff: "                    + copiedStaff.getStaffNames().size());        System.out.println(staff.hashCode());            System.out.println(copiedStaff.hashCode());    } catch (CloneNotSupportedException e) {        e.printStackTrace();    }}//---------------output----------------number of staff: 5number of staff: 521148892731025799482/<code>


每種解決方案始終各有利弊。 永遠記住,解決所有問題的解決方案不只是一種。 因此,在考慮此模式時請使用最佳判斷。

謝謝您的努力。 快樂的編碼。


(本文翻譯自Petey的文章《Creational Design Pattern: Prototype》,參考:https://medium.com/swlh/creational-design-pattern-prototype-9ee91bf111c8)


分享到:


相關文章: