Создайте оболочку только для чтения над классом - PullRequest
1 голос
/ 16 декабря 2011

У меня есть класс, подобный следующему:

 class A{
  // it has some getters and setters
 }

Есть еще один класс, называемый классом конструктора, который создает класс A

class BuilderA{
   // builds A and returns an instance.
}

Теперь я хочу подготовить класс A для чтения, который делаетУбедитесь, что в Class newA будут только получатели ClassA, а не сеттеры.

Я делаю это, чтобы удостовериться, что если я передам это newA, я в безопасности, что никто не сможет использовать геттеры и внести какие-либо изменения в newA, что может произойти, если я использую класс A напрямую.Кто-нибудь может сказать мне, как я могу этого достичь? ..

Ответы [ 4 ]

1 голос
/ 16 декабря 2011

Вот пример:

public class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

public class ImmutablePerson extends Person {

    public ImmutablePerson(String name) {
        super(name);
    }

    @Override
    public void setName(String name) {
        throw new UnsupportedOperationException();
    }
}

public class PersonBuilder {
    public static Person createMutablePerson(String name) {
        return new Person(name);
    }

    public static Person createImmutablePerson(String name) {
        return new ImmutablePerson(name);
    }
}

Хотя это работает, я не думаю, что это отличный способ разработки классов в Java.

Обращаясь к "Эффективной Java" Джошуа Блоха, классы должны быть неизменяемыми, если только у вас нет веских причин, по которым они должны быть изменяемыми.

0 голосов
/ 16 декабря 2011

Вы можете легко использовать Proxy для этого (java.lang.reflect.Proxy), тогда вы просто посмотрите на имя вызванного метода (проверьте, начинается ли оно с set, примерно).Затраты должны быть относительно минимальными, и они работают без необходимости что-то кодировать для каждого дополнительного класса.Вы можете использовать аннотации с дальнейшим кодированием для указания сеттеров, которые разрешены / запрещены.

public static boolean isSetter(Method method){
    if(!method.getName().startsWith("set"))    return false;
    if(method.getParameterTypes().length != 1) return false;  
    return true;
}
0 голосов
/ 16 декабря 2011

Вы можете расширить класс A и реализовать сеттеры, которые генерируют исключение UnsupportedOperationException или просто ничего не делают при вызове. Вы не можете закрыть доступ к общедоступным методам установки класса A и оставаться экземпляром класса A (через подклассы).

0 голосов
/ 16 декабря 2011

Если вы хотите общее решение проблемы, вам придется извлечь геттеры и сеттеры в интерфейс, а затем использовать Proxy для перехвата всех методов, начиная с set, или их аннотирования (и обработки аннотаций в вашем обработчике), а затем либо ничего не делать, либо, предпочтительно, выбросить исключение UnsupportedOperationException.

Это было бы излишним, если бы оно понадобилось только для 1 или 2 классов, и в общем случае с большими накладными расходами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...