До сих пор я везде видел, что шаги по созданию шаблона нулевого объекта, например, в BST для удаления нулевых проверок, следующие:

  1. Создайте интерфейсный узел

  2. Создайте два класса, реализующих интерфейс Node. Один из которых будет real_Node, а другой - null_Node.

  3. Используя эти классы, нулевые проверки могут быть удалены в классе BST при создании дерева.

Теперь я хочу знать, есть ли другие способы сделать это, например, можем ли мы реализовать шаблон нулевого объекта без интерфейса, используя только классы, т.е. на шаге выше (1.) можем ли мы использовать класс узла вместо интерфейса узла.

2
Nazgul 29 Фев 2016 в 02:04
"статические классы" Статический класс - это просто тип вложенного класса, поэтому я не понимаю, какое отношение он имеет к шаблону нулевого объекта. Измените свой вопрос и постарайтесь пояснить, о чем вы спрашиваете.
 – 
Radiodef
29 Фев 2016 в 02:08
Спасибо, я хочу спросить, можем ли мы в (1.) использовать класс Node вместо интерфейса Node.
 – 
Nazgul
29 Фев 2016 в 02:14

1 ответ

Лучший ответ

Да, есть способы реализовать шаблон объекта Null без явного использования Java interface. Однако вы действительно делаете то же самое, что и YMMV. Вы можете столкнуться с проблемами, если у вас нет доступа к базовому классу и / или он не позволяет какую-либо форму расширения / переопределения.

  • Создайте класс, который расширяет ваш базовый класс, но выполняет «нулевые» операции, переопределяя их. Обычно вы скрываете его за каким-то статическим конструктором для облегчения доступа.

    class Base {
        public void someMethod() {
            // this stuff does the non-null behaviour
        }
    
        public static Base nullVersion() {
            return new NullOfBase();
        }
    
        private static class NullOfBase extends Base {
            @Override
            public void someMethod() {
               // this guy does the null version.
            }
        }
    }
    
  • Используйте анонимный класс для статического члена класса «NULL», который переопределяет различные операции, которые вам нужно переопределить.

    public class Base {
       public static final Base NULL = new Base() {
            @Override
            public void someMethod() {
               // this guy does the null version.
            }
        }
    
        public void someMethod() {
            // this stuff does the non-null behaviour
        } 
    }
    
  • Используйте абстрактный класс для хранения операций, которые являются общими как для ненулевой, так и для нулевой реализаций, помечая эти методы как окончательные, все другие методы являются абстрактными и реализованы в двух конкретных классах - один для ненулевой функциональности, а другой для нулевая функциональность. Вы можете использовать статические конструкторы, чтобы упростить создание общих вариантов использования и скрыть конкретные имена классов от просмотра.

    public abstract class Base {
         public final sayHello() {
             System.out.println("Hello world");
         }
    
         public abstract void someMethod();
    
         public static Base nonNullVersion() {
             return new NonNullBase();
         }
    
         public static Base nullVersion() {
             return new NullBase();
         }
    
         private static final class NonNullBase extends Base {
            @Override
            public void someMethod() {
                // this stuff does the non-null behaviour
            }
         }
    
         private static final class NullBase extends Base {
            @Override
            public void someMethod() {
                // this stuff does the null behaviour
            }
         }
    }
    

В качестве альтернативы, иногда NULL-объект на самом деле является просто частным случаем определенного значения (это действительно зависит от того, какие операции над классом). В этом случае у вас может быть статический член с этим значением или статическая фабрика, которая позволяет вам его создать.

3
sisyphus 29 Фев 2016 в 03:12