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

2022-09-05 00:28:03

我正在用这样的类编写一个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;
     }
   }

我的问题:

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

答案 1

执行此操作的常用方法是根本不公开该类,而只是向该类公开接口。一个面向公众的接口和一个面向开发人员的接口。

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

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


    }

答案 2

1)我如何确保此NKMPMIssion类的用户仅访问getters。

你不能。

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

这听起来像是在编写一个 API。如果从该 API 的公共方法返回实例,则可以调用 setter。即使您标记了它们 或 ,它们仍然可以通过反射来调用。也就是说,通常使它们不 - 就足够了。它至少会说:“如果你打电话给这些,你就在不受支持的领域。NKMPMIssionprivateprotectedpublic

如果要使其更加困难,可以返回一个将外观包裹在实例周围的实例。但这只会使它变得更加困难,而不是不可能,因为立面实例必须具有对实例的引用,该实例(即使它是)可以通过反射访问。NKMPMIssionNKMPMIssionprivate


推荐