Разрешить создавать экземпляры определенного класса только одним другим классом в Java?

Предположим, что у меня есть два класса A и B, и я хочу сделать так, чтобы экземпляры B можно было создавать только в A и в самом B. Я не хочу, чтобы какой-либо другой класс (включая подклассы A) мог создавать экземпляры B. Есть ли способ сделать это в Java?

Вот немного кода, если не ясно, что я пытаюсь сделать:

public class A {
    B instance;
    public A(){
        // Still allows for subclasses to access B
        instance = B.getInstance((Object)this);
    }
}

Вот класс, конструкцию которого я хочу ограничить:

public class B {

    // If I make this public all classes can create it, but
    // if I make it private without any getter methods then
    // no other classes but itself can create it
    private B(){}

    // Problem with this is that subclasses of  A
    // can also create instances of B
    public static B getInstance(Object o){
        if(o instanceof A)
            return new B();
        else
            return null;
    } 
}

Я пробовал поиск в Google и поиск в Stackru возможных решений, но самое близкое, что я обнаружил, - это использование шаблона проектирования Singleton с измененным методом getInstance(), чтобы убедиться, что только класс определенного типа может иметь доступ к экземплярам класса. B. Хотя это работает довольно хорошо, он все же позволяет любому подклассу, который расширяет A, получать экземпляры B. Есть ли какой-нибудь способ, чтобы это не происходило или это разрушило бы весь смысл подкласса, если подкласс не мог сделать то, что его суперкласс может сделать?

4 ответа

Решение

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

Вы можете сделать B частным внутренним классом класса A.

Хотя это работает довольно хорошо, он все же позволяет любому подклассу, который расширяет A, получать экземпляры B. Есть ли какой-либо способ, чтобы это не происходило или это разрушило бы весь смысл подкласса, если подкласс не мог сделать то, что мог бы сделать его суперкласс?

Если вы не хотите, чтобы ваш класс A был разделен на подклассы, вы можете сделать класс A финальным или иметь собственный конструктор для A. Хотя, как предлагалось в предыдущих ответах, лучше создавать частные внутренние классы.

public final class A {
    B instance;
    public A(){
        // Still allows for subclasses to access B
        instance = B.getInstance((Object)this);
    }
}

A может представить что-то B только это A может обладать. Например

public class A
{
    public static class Pass
    {
        private Pass(){}

Только A может создать A.Pass объект. Если такие объекты передаются только от A в Bникто больше не может их заполучить и притвориться A,

public class B
{
    public static B getInstance(A.Pass token)
    {
        if(pass==null) 
            throw ...      
        else
            caller must be A

Этот класс сгенерирует исключение, если создающий класс не B

class A {

    A() {
        new SecurityManager() {
            {
                if (getClassContext()[1] != B.class) {
                    throw new IllegalStateException();
                }
            }
        };
    }
...

Вы не можете сломать это даже с отражением

Другие вопросы по тегам