仅将getter方法共享给客户端的最佳方法是什么?

Dru*_*ter 12 java

我正在用这样的类编写一个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;
     }
   }
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. 如何确保此类的用户NKMPMission只访问getter?
  2. 如何为这个功能引入setter,以便我作为开发人员可以设置,但用户无法设置?

Old*_*eon 21

通常的方法是不公开类,只是公开该类的接口.一个公共界面和一个开发人员界面.

然后,您需要一个工厂来创建它们.

/**
 * 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

对于真正的偏执狂,你甚至可以使用代理.这将使得通过反射使用设定者变得困难(但并非不可能).

    /**
     * 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();
        }


    }
Run Code Online (Sandbox Code Playgroud)


T.J*_*der 6

1)我如何确保此NKMPMIssion类的用户只能访问getter.

你不能.

2)我如何为此功能引入setter,以便作为开发人员我应该能够设置,但用户不应该设置.

这听起来像是在编写API.如果NKMPMIssion从该API的公共方法返回实例,则可以调用setter.即使你将它们标记private或者protected,他们仍然可以通过反射调用.也就是说,通常使它们不合适public就足够了.它至少会说:"如果你打电话给这些,你就处于不受支持的领域."

如果您想使其更难,您可以返回一个围绕实例包裹外观NKMPMIssion实例.但这只会让它变得更难,而不是不可能,因为外观实例必须具有对实例的引用NKMPMIssion,即使它private可以通过反射访问(即使它是).


Sur*_*tta 2

看来你正在尝试编写一个 API。假设用户是指使用您的 API 的开发人员。

在这种情况下,将 setter 设置为protected并构建一些有意义的包结构,以便只有子成员和包成员可以看到它。

如果您想保护它免受儿童的侵害,除了将其设为私有之外,别无他法。

  • 投反对票的人,愿意发表评论吗?如果答案有误,请纠正我们。最好的事情是,添加您的答案,以便我们可以从中学习。 (4认同)