2009-02-04 4 views
6

Я читаю книгу Джоша Блоха Эффективная Java, и он предлагает использовать шаблон проектирования строителя при создании объектов с большим количеством членов. Из того, что я вижу, это не шаблон дизайна ванили, но выглядит как его вариация. Мне очень нравится его внешний вид и пытаюсь использовать его в веб-приложении C#, которое я пишу. Это код, написанный на Java и работает отличноКак понятие Java статично отличается от C#?

public class Property { 

    private String title; 
    private String area; 

    private int sleeps = 0; 

    public static void main(String[] args) { 

     Property newProperty = new Property.Builder("Test Property").Area("Test Area").Sleeps(7).build(); 

    } 

    private Property(Builder builder) { 
     this.title = builder.title; 
     this.area = builder.area; 
     this.sleeps =builder.sleeps; 
    } 

    public static class Builder{ 
     private String title; 
     private String area; 

     private int sleeps = 0; 

     public Builder (String title){ 
      this.title = title; 
     } 

     public Builder Area(String area){ 
      this.area = area; 
      return this; 
     } 

     public Builder Sleeps(int sleeps){ 
      this.sleeps = sleeps; 
      return this; 
     } 

     public Property build() { 
      return new Property(this); 
     } 
    } 
} 

Когда я это в то, что я думаю, что это C# эквивалента

public class Property 
    { 
    private String title; 
    private String area; 

    private Property(Builder Builder) 
    { 
     title = Builder.title; 
     area = Builder.area; 
    } 


    public static class Builder 
    { 
     // Required parameters 
     private String title; 
     private String area; 

     // Optional parameters 
     private int sleeps = 0; 

     public Builder(String val) 
     { 
      this.title = val; 
     } 

     public Builder Area(String val) 
     { 
      this.area = val; 
      return this; 
     } 

     public Builder Sleeps(int val) 
     { 
      this.sleeps = val; 
      return this; 
     } 

     public Property build() 
     { 
      return new Property(this); 
     } 
    } 
    } 

Тогда я получаю предупреждение компилятора. Большинство из них «не могут объявлять члены экземпляра в статическом классе».

Итак, мой вопрос - во-первых, что я пропустил? Если я что-то пропустил, могу ли я сделать это так, как рекомендует Джош Блох, но на C#, и, наконец, и этот важный тоже, это поточно-безопасный?

+0

Что такое «версия»: P у вас есть эффективная Java? У меня старый, и он не охватывает Builder. Я читал, что это была одна из новых глав, добавленных после опыта Джоша @ Google. – OscarRyz

ответ

3

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

Цель состоит в том, чтобы позволить строителю выполнить шаги, необходимые для создания объекта.

Так (не зная много о C# вы могли бы попробовать что-то вроде этого)

// My naive C# attempt:P 

public class Property 
{ 

    public static void main(String []args) 
    { 
     Property p = Property.buildFrom(new Builder("title").Area("area").Etc()) 
    } 
    public static Property buildFrom(Builder builder) 
    { 
     return new Propert(builder); 
    } 

    private Property (Builder builder) 
    { 
     this.area = builder.area; 
     this.title = builder.title; 
     // etc. 
    } 
} 
public class Builder 
{ 
    public Builder (String t) 
    { 
     this.title = t; 
    } 

    public Builder Area(String area) 
    { 
     this.area = area; 
     return this; 
    } 
    // etc. 
} 

Весь смысл в Builder как статический внутренний класс имущества является создание высокое сцепление между ними (как если бы они где один). Вот почему метод сборки в Builder вызывает частный конструктор «Свойство».

Возможно, на C# вы можете использовать альтернативный артефакт для создания той же связи.

+0

Думаю, я собираюсь попробовать таким образом. Во-первых, потому что я все еще могу иметь представление о требуемых значениях, которые должны быть заданы через конструктор и необязательные значения, которые могут быть созданы с помощью вызовов к строителю. – uriDium

1

Я не уверен, что Java делает с объявлением статического класса, но в C# статический класс - это тот, который имеет только члены класса и по определению не может быть реализован в экземпляр. Это похоже на старую разницу VB между классом и модулем.

2

В Java вложенный класс по умолчанию связан с конкретным экземпляром его содержащего класса. Экземпляр вложенного класса может обращаться к переменным и методам содержащего экземпляра. Если вложенный класс имеет «статическое» ключевое слово, то он не связан с экземпляром внешнего класса. Именно в этом смысле блох использует «статическое» ключевое слово в классе Builder.

«Статический» означает что-то другое при применении к вложенному классу на C#. Я не знаю, какое ключевое слово вы бы использовали в C#, или даже если это необходимо. Вы пытались оставить ключевое слово static из определений классов?

Использование «статических» в определениях классов Java обсуждается в пункте 18 эффективной Java.

+0

Я думаю, что это стандартное определение в Java: вложенные классы могут быть либо статическими, либо нестатическими. Статические вложенные классы просто называются такими; нестатические вложенные классы называются внутренними классами. –

+0

Ссылка на учебное пособие по Java, которое объясняет это: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html –

+0

Упс, небольшая терминологическая икота есть. – DJClayworth

13

public static class в Java означает, что вы определяете статический вложенный класс. Это означает, что он логически содержится в другом классе, но экземпляры его могут существовать без ссылки на его внешний класс. Нестатический вложенный класс называется «внутренним классом», и его экземпляры могут существовать только по отношению к экземпляру внешнего класса.

В C# a static class - это тот, который не может быть создан и, следовательно, не может содержать каких-либо нестатических элементов. На Java нет прямого эквивалента на уровне языка, но вы можете легко предотвратить создание экземпляра Java-класса, предоставив только частный конструктор.

Short Java резюмировать:

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

Я был бы рад, если бы какой-то C# -руру рассказал нам, как внутренние/вложенные классы обрабатываются в C# /. NET.

+0

Я думаю, вы имели в виду * вложенный * вместо * внутреннего * в строке 1. –

+0

Вы правы, я все время смешиваю их. –

+0

«Вложенные классы делятся на две категории: статические и нестатические. Вложенные классы, объявленные как статические, просто называются статическими вложенными классами. Нестатические вложенные классы называются внутренними классами». - Из http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html –

0

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

2

ГАУЫ имеет правильный ответ, но я хотел бы иметь четкое представление о вашем примере, в частности:

В C# версии, вы должны удалить статическое ключевое слово из внутреннего класса. Это не означает то же самое, что и версия Java, и действительно, эффект, который он имеет в версии Java, - это нормальное поведение для внутренних классов в C#.

+0

Есть ли способ получить эффект нестатического внутреннего класса из Java в C#? Чтобы каждый экземпляр внутреннего класса имел неявную ссылку на свой экземпляр внешнего класса? –

+0

Мне тоже любопытно. –

+0

Да, я тоже хотел бы знать. –

0

Я попытаюсь удалить статическое ключевое слово. Моя другая мысль заключалась в том, что, как уже указывали другие, было создано класс строителя как класс высшего уровня.

+0

Это именно то, что вы должны сделать - не делайте строителя классом высшего уровня. –

+0

@SMonkey: Если статическое ключевое слово удалено, тогда не будет способа доступа к построителю без создания свойства сначала. :( – OscarRyz

0

Чтобы ответить на несколько комментариев о том, как получить поведение внутреннего класса Java на C#, казалось бы, что ссылка на охватывающий класс должна быть передана в конструкторе внутреннего класса (из быстрого Google-C# может быть с тех пор добавлена ​​возможность).

public class Outer 
{ 

... 
void SomeMethod() { 
    Inner    workerBee=new Inner(this); 
    } 
... 

    class Inner 
    private Outer outer; 
    { 
    Inner(Outer out) { 
     outer=out; 
     } 
    } 
} 

Так C# только делает явным то, что Java сделал неявно, в том числе явно нуждаясь ссылкой доступа членов внешнего класса.

Лично мне никогда не нравились неявные обращения Java к членам внешних классов, так как кажется слишком легким для отключения и случайного разрушения инкапсуляции - я почти всегда создаю свои внутренние классы как статические и передаю им ссылку на внешний класс.

0

Предполагая, что ваш класс имеет общедоступные свойства, соответствующие членам-конструкторам, вам не нужен шаблон построения Блоха на C#. Вы можете использовать Инициализаторы Object:

public class Property 
{ 

    public String Title {get; set}; 
    public String Area {get; set}; 
    public int Sleeps {get; set}; 

    public static void main(String[] args) 
    { 

     Property newProperty = new Property {Title="Test Property", Area="Test Area", Sleeps=7}; 

    } 
} 

Это не будет возможным, если вам нужно больше инкапсуляции.

+0

Возможно, мне нужно добавить перегруженные методы для некоторых полей, чтобы использовать либо идентификатор, либо фактическое текстовое значение, поэтому свойства не подходят для меня так хорошо. – uriDium

Смежные вопросы