2011-12-16 1 views
1

У меня есть класс, как следует:построить только для чтения обертку над классом

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

Существует еще один класс, называемый конструктор класса, который строит класс А

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

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

Я делаю это, чтобы убедиться, что, если я прохожу этот NEWA я в безопасности, что никто не может использовать методы получения и внесения изменений в NEWA, которые могут произойти, если я использую класс А непосредственно ..

Может кто-нибудь сказать мне, как я могу достичь этого.?

+1

Другой вариант - использовать неизменяемый класс (только геттеры) и создать их с помощью построителя. http://en.wikipedia.org/wiki/Builder_pattern – Stefan

ответ

0

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

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

0

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

1

Вот пример:

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

Хорошо, но это не безопасный тип, вы заметите только во время выполнения, когда кто-то вызывает сеттер на 'ImmutablePerson'. – Jesper

+0

Действительно. Это не очень хороший дизайн. Вот почему я предлагаю пойти на непреложный класс. – SteveD

+0

Этот комментарий не использует ключевое слово extends. Это неверно * во многих отношениях, так как он также вынужден был сказать. Однако предоставляемый им вариант также не является решением вашей проблемы. Вместо этого решением будет вариант 3 https://stackoverflow.com/a/2724848/1502818 –

0

Вы можете легко использовать 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; 
} 
Смежные вопросы