原型设计模式示例
本文是我們名為“ Java設計模式 ”的學院課程的一部分。
在本課程中,您將深入研究大量的設計模式,并了解如何在Java中實現和利用它們。 您將了解模式如此重要的原因,并了解何時以及如何應用模式中的每一個。 在這里查看 !
目錄
1.簡介 2.什么是原型設計模式 3.解決問題 4.何時使用原型設計模式 5. JDK中的原型模式 6.下載源代碼1.簡介
在面向對象編程中,您需要使用對象。 對象彼此交互以完成工作。 但是有時候,創建沉重的對象可能會變得很昂貴,并且如果您的應用程序需要太多此類對象(包含幾乎相似的屬性),則可能會帶來一些性能問題。
讓我們考慮一個應用程序需要一些訪問控制的場景。 用戶可以根據提供給他們的訪問權限來使用應用程序的功能。 例如,有些用戶有權訪問由應用程序生成的報告,而有些則不能。 他們中有些甚至可以修改報告,而有些只能讀取報告。 一些用戶還具有添加或什至刪除其他用戶的管理權限。
每個用戶對象都有一個訪問控制對象,用于提供或限制應用程序的控件。 此訪問控制對象是一個笨重的對象,其創建非常昂貴,因為它需要從某些外部資源(例如數據庫或某些屬性文件等)中獲取數據。
我們也不能與同一級別的用戶共享同一訪問控制對象,因為管理員可以在運行時更改權限,并且同一級別的其他用戶可以具有不同的訪問控制。 一個用戶對象應具有一個訪問控制對象。
我們可以使用原型設計模式來解決此問題,方法是一次在所有級別上創建訪問控制對象,然后在需要時向用戶提供該對象的副本。 在這種情況下,從外部資源獲取數據僅發生一次。 下次,通過復制現有對象來創建訪問控制對象。 每次發送請求時,都不會從頭開始創建訪問控制對象。 這種方法肯定會減少對象創建時間。
在深入探討解決方案之前,請讓我們進一步了解原型設計模式。
2.什么是原型設計模式
原型設計模式用于指定要使用原型實例創建的對象的種類,并通過復制此原型來創建新對象。
其概念是復制現有對象,而不是從頭開始創建新實例,這可能包括昂貴的操作。 現有對象充當原型,并包含對象的狀態。 僅在需要時,新復制的對象才能更改相同的屬性。 這種方法節省了昂貴的資源和時間,尤其是在對象創建很繁重的過程中。
在Java中,有某些方法可以復制對象以創建一個新對象。 實現此目的的一種方法是使用Cloneable接口。 Java提供了clone方法,該方法從Object類繼承Object 。 您需要實現Cloneable接口,并根據需要覆蓋此clone方法。
圖1
原型
- 聲明一個用于克隆自身的接口。
具體原型
- 實現克隆自身的操作。
客戶
- 通過要求原型克隆自己來創建新對象。
原型使您可以通過向客戶端注冊原型實例來將新的具體產品類合并到系統中。
3.解決問題
在此解決方案中,我們將使用克隆方法來解決上述問題。
package com.javacodegeeks.patterns.prototypepattern;public interface Prototype extends Cloneable {public AccessControl clone() throws CloneNotSupportedException;}上面的接口擴展了Cloneable接口,并包含方法clone 。 該接口由要創建原型對象的類實現。
package com.javacodegeeks.patterns.prototypepattern;public class AccessControl implements Prototype{private final String controlLevel;private String access;public AccessControl(String controlLevel,String access){this.controlLevel = controlLevel;this.access = access;}@Overridepublic AccessControl clone(){try {return (AccessControl) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}public String getControlLevel(){return controlLevel;}public String getAccess() {return access;}public void setAccess(String access) {this.access = access;}}AccessControl類實現Prototype接口并覆蓋clone方法。 該方法調用超類的clone方法,并將對象向下轉換為AccessControl類型后返回該對象。 clone方法將引發CloneNotSupportedException ,該方法本身會捕獲該異常。
該類還包含兩個屬性; controlLevel用于指定此對象包含的控制級別。 級別取決于要使用它的用戶類型,例如USER,ADMIN,MANAGER等。
另一個屬性是access ; 它包含用戶的訪問權限。 請注意,為簡單起見,我們將訪問權限用作String類型屬性。 這可以是Map類型,可以包含分配給用戶的長訪問權限的鍵值對。
package com.javacodegeeks.patterns.prototypepattern;public class User {private String userName;private String level;private AccessControl accessControl;public User(String userName,String level, AccessControl accessControl){this.userName = userName;this.level = level;this.accessControl = accessControl;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getLevel() {return level;}public void setLevel(String level) {this.level = level;}public AccessControl getAccessControl() {return accessControl;}public void setAccessControl(AccessControl accessControl) {this.accessControl = accessControl;}@Overridepublic String toString(){return "Name: "+userName+", Level: "+level+", Access Control Level:"+accessControl.getControlLevel()+", Access: "+accessControl.getAccess();}}User類具有userName , level和對分配給它的AccessControl的引用。
我們使用了一個AccessControlProvider類,該類預先創建和存儲可能的AccessControl對象。 當有對AccessControl對象的請求時,它將返回一個通過復制存儲的原型創建的新對象。
package com.javacodegeeks.patterns.prototypepattern;import java.util.HashMap; import java.util.Map;public class AccessControlProvider {private static Map<String, AccessControl>map = new HashMap<String, AccessControl>();static{System.out.println("Fetching data from external resources and creating access control objects...");map.put("USER", new AccessControl("USER","DO_WORK"));map.put("ADMIN", new AccessControl("ADMIN","ADD/REMOVE USERS"));map.put("MANAGER", new AccessControl("MANAGER","GENERATE/READ REPORTS"));map.put("VP", new AccessControl("VP","MODIFY REPORTS"));}public static AccessControl getAccessControlObject(String controlLevel){AccessControl ac = null;ac = map.get(controlLevel);if(ac!=null){return ac.clone();}return null;} }getAccessControlObject方法根據傳遞給它的controlLevel獲取存儲的原型對象,并將新創建的克隆對象返回到客戶端代碼。
現在,讓我們測試代碼。
package com.javacodegeeks.patterns.prototypepattern;public class TestPrototypePattern {public static void main(String[] args) {AccessControl userAccessControl = AccessControlProvider.getAccessControlObject("USER");User user = new User("User A", "USER Level", userAccessControl);System.out.println("************************************");System.out.println(user);userAccessControl = AccessControlProvider.getAccessControlObject("USER");user = new User("User B", "USER Level", userAccessControl);System.out.println("Changing access control of: "+user.getUserName());user.getAccessControl().setAccess("READ REPORTS");System.out.println(user);System.out.println("************************************");AccessControl managerAccessControl = AccessControlProvider.getAccessControlObject("MANAGER");user = new User("User C", "MANAGER Level", managerAccessControl);System.out.println(user);} }上面的代碼將產生以下輸出:
Fetching data from external resources and creating access control objects... ************************************ Name: User A, Level: USER Level, Access Control Level:USER, Access: DO_WORK Changing access of: User B Name: User B, Level: USER Level, Access Control Level:USER, Access: READ REPORTS ************************************ Name: User C, Level: MANAGER Level, Access Control Level:MANAGER, Access: GENERATE/READ REPORTS在上面的代碼中,我們在USER級別創建了一個AccessControl對象,并將其分配給UserA。然后,又將另一個AccessControl對象分配給User B,但是這次我們更改了User B的訪問權限。最后,MANAGER用戶C的級別訪問控制。
getAccessControlObject用于獲取AccessControl對象的新副本,當我們更改用戶B的訪問權限時,可以清楚地看到這一點,而對于用戶A的訪問權限沒有更改(只需再次打印用戶A對象)。 這確認clone方法工作正常,因為它返回對象的新副本,而不是指向同一對象的引用。
4.何時使用原型設計模式
當系統應獨立于其產品的創建,組成和表示方式時,請使用原型模式。 和
- 在運行時指定要實例化的類時,例如,通過動態加載; 要么
- 為了避免建立與產品的類層次結構平行的工廠的類層次結構; 要么
- 當一個類的實例只能具有幾種不同的狀態組合之一時。 安裝相應數量的原型并克隆它們,而不是每次都以適當的狀態手動實例化類,可能會更方便。
5. JDK中的原型模式
- java.lang.Object#clone()
- java.lang.Cloneable
6.下載源代碼
這是關于原型設計模式的課程。 您可以在此處下載源代碼: PrototypePattern-Project
翻譯自: https://www.javacodegeeks.com/2015/09/prototype-design-pattern.html
總結
- 上一篇: 因 AI 生成出版物泛滥,亚马逊要求图书
- 下一篇: jax-rs jax-ws_Tomcat