[英]What is the best way to share only the getter methods to client?
我正在用這樣的類編寫一個API:
public class NKMPMission {
private String name;
private int age;
public NKMPMission(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
我的問題:
NKMPMission
類的用戶僅訪問getter? 通常的方法是不公開類,只是公開該類的接口。 一個公共界面和一個開發人員界面。
然后,您需要一個工廠來創建它們。
/**
* Expose this interface to the public.
*/
public interface INKMPMission {
public String getName();
public int getAge();
}
/**
* Only expose this interface to developers.
*/
interface IDeveloperNKMPMission {
public void setName(String name);
public void setAge(int age);
}
public static class NKMPMissionFactory {
/**
* Expose only the INKMPMission construction.
*/
public INKMPMission make(String name, int age) {
return new NKMPMission(name, age);
}
/**
* Protected version for developers.
*/
IDeveloperNKMPMission forDeveloper(INKMPMission it) {
return IDeveloperNKMPMission.class.cast(it);
}
/**
* Private so no-one outside the factory knows about the inner workings.
*/
private static class NKMPMission implements INKMPMission, IDeveloperNKMPMission {
private String name;
private int age;
private NKMPMission(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String getName() {
return name;
}
@Override
public int getAge() {
return age;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public void setAge(int age) {
this.age = age;
}
}
}
對於真正的偏執狂,你甚至可以使用代理。 這將使得通過反射使用設定者變得困難(但並非不可能)。
/**
* Expose only the INKMPMission construction.
*/
public INKMPMission make(String name, int age) {
return new NKMPMissionProxy(new NKMPMission(name, age));
}
/**
* Protected version for developers.
*/
protected IDeveloperNKMPMission forDeveloper(INKMPMission it) {
if (it instanceof NKMPMissionProxy) {
it = ((NKMPMissionProxy) it).theMission;
}
return IDeveloperNKMPMission.class.cast(it);
}
/**
* A proxy for the truly paranoid - makes using reflection more difficult (but not impossible)
*/
private static class NKMPMissionProxy implements INKMPMission {
private final NKMPMission theMission;
private NKMPMissionProxy(NKMPMission theMission) {
this.theMission = theMission;
}
@Override
public String getName() {
return theMission.getName();
}
@Override
public int getAge() {
return theMission.getAge();
}
}
1)我如何確保此NKMPMIssion類的用戶只能訪問getter。
你不能。
2)我如何為此功能引入setter,以便作為開發人員我應該能夠設置,但用戶不應該設置。
這聽起來像是在編寫API。 如果從該API的公共方法返回NKMPMIssion
實例,則可以調用setter。 即使您將它們標記為private
或protected
,它們仍然可以通過反射進行調用。 也就是說,通常讓他們不public
就足夠了。 它至少會說:“如果你打電話給這些,你就處於不受支持的領域。”
如果你想讓它變得更難,你可以返回一個圍繞NKMPMIssion
實例包裝外觀的實例。 但這只會讓它變得更難,而不是不可能,因為外觀實例必須引用NKMPMIssion
實例,即可以通過反射訪問它(即使它是private
)。
最簡單的方法是使API僅使用接口,並使該類成為實現細節。
public interface INKMPMission {
String getName();
int getAge();
}
public class SomeService{
private class MyNKMPMission implements INKMPMission {
//put getters and setters here
}
public List<INKMPMission> getMissions(){
//put some MyNKMPMissions in a list
}
}
由於MyNKMPMission是私有的,因此消費者將無法進行向下轉換並訪問設置者。
你可以 (以某種方式),但你不應該這樣做:
這種方式既不漂亮也不快,因為您必須檢查每次訪問setter。
另一種方法是使用@CallerSensitive
Annotation,雖然它是propritary API,因此不適用於所有平台/ jre實現: https ://stackoverflow.com/a/22627383/1164913
干凈,在大多數情況下是足夠的方式將使用一個接口,它只向客戶端提供getter,並將其返回給客戶端。
您似乎正在嘗試編寫API。 假設用戶意味着使用您的API的開發人員。
在這種情況下,將setter設置為protected
並構建一些有意義的包結構,這樣只有child和package成員才能看到它。
如果你想保護它甚至是孩子的,除了把它變成私人之外別無他法。
回答問題:
Q1。 你不能像TJ克勞德在他的回答中所說的那樣。
Q2。 我建議您按照以下順序嘗試以下事項,從最簡單到最難,並采取您認為最適合努力回報的選項:
我會怎么做:
如果您的類集將在內部使用,那么我將選項1與良好的javadoc和項目標准相結合,它應該就足夠了。
如果您要創建公共API,我會選擇2。
恕我直言,選項3在這種情況下增加了太多不必要的復雜性,並且很少受益,因為無論如何都可以訪問每個類方法或屬性拋出反射(正如許多人所提到的)。 我想每個人都知道,對API的隱藏方法的訪問拋出反射是hacky,危險並且不方便項目的管理,因為API提供者有權更改隱藏的方法實現,而無需進一步通知最終用戶。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.