Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Модифицированый паттерн Builder и наследование 
:(
    Опции темы
xaoc2
Дата 28.10.2009, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 22.10.2004

Репутация: нет
Всего: нет



Существует паттерн builder. И существует его его модифицированая версия для Java с внутренним классом, которая позволяет 
заинициализировать объект значениями. При этом объект не обязан иметь сеттеры. То есть получаем безопасный ( не можем извне модифицировать)  инициализированый объект. Ниже привожу пример. Вопрос: как развить эту идею, если я хочу иметь наследника MojKlass Например, MojKlass2 . Скорее всего продётся добавить метод newBuilderKlass2. Дальше не знаю стоит ли вводить новый класс буилдера в класс MojKlass2, но ! если бы я использовал функциональность MojKlassBuilder, то методы  setPole1 возвращают обект MojKlassBuilder и не получилось ны сделать:



Код

        MojKlass2 obj = MojaKlasa2.newBuilderKlass2()
                .setPole1("aaa")
                .setPole2("bbb")
                .setPole3("ccc")
                .setNovoePole("ddd") // Ошибка!!! setPole3 возвращает объект MojKlassBuilder у которого нет метода setNovoePole

Имеется вииду, что в моя MojaKlasa2  будет добавлен такой код:
Код

class MojaKlasa2 extends MojKlass
{
      protected  String novoePole;
      .............................
     public static MojKlassBuilder2 newBuilderKlass2(){
        return new MojKlassBuilder2();
    }
     ..........................
    public static class MojKlassBuilder2 extends MojKlassBuilder
    {
          ................
          ................
          public MojKlassBuilder2 setNovoePole(String s)
          {
              buildObject.novoePole= s;
              return this;
          }
    }
}

Как избежать дублирования кода ? Чтобы не писать полностью новый код для MojKlass2.MojKlassBuilder2

Вот работающий пример без наследования:

Код

package testbuilder;
public class MojKlass {
    protected String pole1;
    protected String pole2;
    protected String pole3;

    private MojKlass(){}

    @Override
    public String toString() {
        return pole1 + "." + pole2 + "." + pole3;
    }

    public static MojKlassBuilder newBuilder(){
        return new MojKlassBuilder();
    }
    
   public static class MojKlassBuilder
   {
       private MojKlass buildObject;
       private MojKlassBuilder(){
           buildObject = new MojKlass();
       }
       public MojKlassBuilder setPole1(String s)
       {
           buildObject.pole1 = s;
           return this;
       }
       public MojKlassBuilder setPole2(String s)
       {
           buildObject.pole2 = s;
           return this;
       }
       public MojKlassBuilder setPole3(String s)
       {
           buildObject.pole3 = s;
           return this;
       }
       public MojKlass build()
       {
           return buildObject;
       }
   }
}


Код

package testbuilder;
public class Main {
    public static void main(String[] args) {
        MojKlass obj = MojKlass.newBuilder()
                .setPole1("aaa")
                .setPole2("bbb")
                .setPole3("ccc")
                .build();

        System.out.println(obj);
    }
}


PM MAIL   Вверх
xaoc2
Дата 28.10.2009, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 22.10.2004

Репутация: нет
Всего: нет



Придумал такое решение, немного головоломное.... Думаю руководитель проекта не разрешит такое использовать:
Код

package testbuilder;

import java.lang.reflect.Constructor;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MojKlass {
    protected String pole1;
    protected String pole2;
    protected String pole3;

    public MojKlass(){}

    @Override
    public String toString() {
        return pole1 + "." + pole2 + "." + pole3;
    }

   protected static
   <TO extends MojKlass, BUILDER  extends  MojKlassBuilder<TO, BUILDER> >
   BUILDER
   newBuilder(Class<TO> clazzObject, Class<BUILDER> clazz )
   {
        try {
            Constructor<BUILDER> constructor = clazz.getConstructor(clazzObject.getClass());
            BUILDER builder = constructor.newInstance(clazzObject);
            return builder;
        } catch (Exception ex) {
            Logger.getLogger(MojKlass.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
        
   }

   public static MojKlassConcretBuilder newBuilderMojClass()
   {
       return MojKlass.<MojKlass, MojKlassConcretBuilder>newBuilder(MojKlass.class, MojKlassConcretBuilder.class);
   }
    public MojKlass(String pole1, String pole2, String pole3) {
        this.pole1 = pole1;
        this.pole2 = pole2;
        this.pole3 = pole3;
    }
   public static class MojKlassConcretBuilder extends MojKlassBuilder<MojKlass, MojKlassConcretBuilder>
   {

        public MojKlassConcretBuilder(Class<MojKlass> clazz) {
            super(clazz);
        }
   }

   protected static class MojKlassBuilder<TO extends MojKlass, BUILDER extends MojKlassBuilder>
   {
       protected TO buildObject;
       protected MojKlassBuilder(Class<TO> clazz){
            try {
                buildObject = clazz.newInstance();
            } catch (Exception ex) {
                Logger.getLogger(MojKlass.class.getName()).log(Level.SEVERE, null, ex);
            }
       }
       public BUILDER  setPole1(String s)
       {
           buildObject.pole1 = s;
           return (BUILDER)this;
       }
       public BUILDER setPole2(String s)
       {
           buildObject.pole2 = s;
           return (BUILDER)this;
       }
       public BUILDER setPole3(String s)
       {
           buildObject.pole3 = s;
           return (BUILDER)this;
       }
       public TO build()
       {
           return buildObject;
       }
   }
}



Код

package testbuilder;

public class MojKlass2 extends MojKlass{
    protected String nowojePole;

    public MojKlass2() {
        super();
    }

    @Override
    public String toString() {
        return super.toString() + "."+nowojePole;
    }

   public static MojKlass2Builder2 newBuilderMojClass2()
   {
       return MojKlass.<MojKlass2, MojKlass2Builder2>newBuilder(MojKlass2.class, MojKlass2Builder2.class);
   }

   protected static class MojKlass2Builder2 extends MojKlassBuilder<MojKlass2, MojKlass2Builder2>
   {
       public MojKlass2Builder2(Class<MojKlass2> clazz) {
            super(clazz);
       }

       public MojKlass2Builder2 setNovojePole(String s)
       {
            buildObject.nowojePole = s;
            return this;
       }
    }
}


Код

package testbuilder;
public class Main {
    public static void main(String[] args) {

        MojKlass obj = MojKlass.newBuilderMojClass()
                     .setPole1("aaa")
                     .setPole2("bbb")
                     .setPole3("ccc")
                     .build();

        System.out.println(obj);  // Out: aaa.bbb.ccc


        MojKlass2 obj2 = MojKlass2.newBuilderMojClass2()
                     .setPole1("aaa")
                     .setPole2("bbb")
                     .setPole3("ccc")
                     .setNovojePole("ddd")
                     .build();
        System.out.println(obj2); // Out: aaa.bbb.ccc.ddd
    }
}


Это сообщение отредактировал(а) xaoc2 - 28.10.2009, 17:40
PM MAIL   Вверх
4EJIOBEK
Дата 28.10.2009, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 26.3.2007

Репутация: нет
Всего: 4



Код

public class MoyKlass {
    protected MoyKlass(){}
    
    public static class MoyKlassBuilder{
        public static MoyKlass getMoyKlass(){
            return new MoyKlass();
        }
    }
}

Код


public class MoyKlass2 extends MoyKlass {
    
    protected MoyKlass2() {
        super();
    }
    
    public static class MoyKlassBuilder extends MoyKlass.MoyKlassBuilder{
        public static MoyKlass2 getMoyKlass(){
            return new MoyKlass2();
        }
        /// добавляем сеттеры к новым полям
    }
}

Код

public class MoyKlassFactory {
    public static MoyKlass createMoyKlass1(/* список параметров */){
        return MoyKlass.MoyKlassBuilder.getMoyKlass().setPole1();//и далее сетты для остальных полей как и было
    }
    public static MoyKlass2 createMoyKlass2(/* список параметров */){
        return MoyKlass2.MoyKlassBuilder.getMoyKlass().setPole1();//и далее сетты для остальных полей как и было
    }
}


как вариант

Это сообщение отредактировал(а) 4EJIOBEK - 28.10.2009, 17:09
PM MAIL ICQ   Вверх
xaoc2
Дата 28.10.2009, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 22.10.2004

Репутация: нет
Всего: нет



Цитата

return MoyKlass.MoyKlassBuilder.getMoyKlass().setPole1();

Не, не подойдёт, потому что классы MoyKlass и MoyKlass2  не имеют сеттеров.
Это основная идея этого паттерна - создать немодифицируемый извне объект.
PM MAIL   Вверх
Andy_L20066
Дата 28.10.2009, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 177
Регистрация: 10.3.2008

Репутация: нет
Всего: 1



вот просто для интереса запустил предыдущую програму, модифицыровал немножко, вышло что-то вот такое, но работаетsmile (на мой взгляд некрасиво как-то получилось)

Код

abstract class T {
    public MoyKlass setPoleNovoje(String s2){
        return null;
    }
    
    public void print(){}
}

class MoyKlass extends T{
    String pole1;
    
    protected MoyKlass(){}
    
    public static class MoyKlassBuilder{
        public static MoyKlass getMoyKlass(){
            return new MoyKlass();
        }
    }
    
    public MoyKlass setPole1(String s1){
     this.pole1 = s1;
     return this;
    }
    public void print(){
     System.out.println(pole1 + " ");
    }
}

class MoyKlass2 extends MoyKlass {
    String novojePole;
    
    protected MoyKlass2() {
        super();
    }
    
    public static class MoyKlassBuilder extends MoyKlass.MoyKlassBuilder{
        public static MoyKlass2 getMoyKlass(){
            return new MoyKlass2();
        }
    }
    
    public MoyKlass setPoleNovoje(String s2){
     this.novojePole = s2;
     return this;
    }
   
    public void print(){
     System.out.println(pole1 + " " + novojePole);
    }
    
}

class MoyKlassFactory {
    public static MoyKlass createMoyKlass1(){
        return MoyKlass.MoyKlassBuilder.getMoyKlass().setPole1("Klass1");
    }
    public static MoyKlass createMoyKlass2(){
        return MoyKlass2.MoyKlassBuilder.getMoyKlass().setPole1("Klass2").setPoleNovoje("Novoje");
    }
}

public class AbstractTest {

    public static void main(String[] args) {
        new MoyKlassFactory().createMoyKlass2().print();
        new MoyKlassFactory().createMoyKlass1().print();
    }

}



Это сообщение отредактировал(а) Andy_L20066 - 28.10.2009, 18:26
PM MAIL ICQ   Вверх
4EJIOBEK
Дата 28.10.2009, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 26.3.2007

Репутация: нет
Всего: 4



что мешает немного подправить?)
Код

public class MoyKlass2 extends MoyKlass {
    
    private Object poleN;

    protected MoyKlass2() {
        super();
    }
    
    public static class MoyKlassBuilder extends MoyKlass.MoyKlassBuilder{
        private MoyKlass2 moyKlass;

        private MoyKlassBuilder(){
            moyKlass = new MoyKlass2();
        }

        public static MoyKlassBuilder createBuilder(){
            return new MoyKlassBuilder ();
        }

        public MoyKlassBuilder setPoleN(Object poleValue){
            moyKlass.poleN = poleValue;
        }

        public MoyKlass2 build(){
            return moyKlass;
        }

        public MoyKlass2
        /// добавляем сеттеры к новым полям
    }
}


и подправить код MoyKlass1 соответсвенно

Это сообщение отредактировал(а) 4EJIOBEK - 28.10.2009, 18:29
PM MAIL ICQ   Вверх
xaoc2
Дата 29.10.2009, 00:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 74
Регистрация: 22.10.2004

Репутация: нет
Всего: нет



4EJIOBEK:
Цитата

Код

public static class MoyKlassBuilder extends MoyKlass.MoyKlassBuilder......
{
    ...... // старые сеттеры не будут работать, так как они работают со своей
    .....  // копией   private MoyKlass moyKlass, и не будут устанавливать значения для  private MoyKlass2 moyKlass
     ......//полиморфизм для полей не работает !

......
.....

/// добавляем сеттеры к новым полям
.......



Любой сеттер из старого класса возвращает класс MoyKlassBuilder  из MoyKlass, хотя он называется также как  MoyKlassBuilder, но это всегда   MoyKlass.MoyKlassBuilder  а не  MoyKlass2.MoyKlassBuilder
PM MAIL   Вверх
4EJIOBEK
Дата 29.10.2009, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 26.3.2007

Репутация: нет
Всего: 4



сорри накидал в прошлый раз, что пришло в голову, сам не проверял

немного реабилитируюсь, конечно не оч. красиво получилось

Код

public class MoyKlass {
    
    private String pole1;
    private String pole2;
    
    protected MoyKlass(){}
    public String getPole1() {
        return pole1;
    }
    public String getPole2() {
        return pole2;
    }

    public static class MoyKlassBuilder{
        protected MoyKlass moyKlass;
        protected MoyKlassBuilder(){
            init();
        }
        protected void init(){
            moyKlass = new MoyKlass();
        }
        public static MoyKlassBuilder createMoyKlassBuilder(){
            return new MoyKlassBuilder();
        }
        public MoyKlassBuilder setPole1(String pole1){
            moyKlass.pole1 = pole1;
            return this;
        }
        public MoyKlassBuilder setPole2(String pole2){
            moyKlass.pole2 = pole2;
            return this;
        }
        public MoyKlass build(){
            return moyKlass;
        }
    }
}


Код

public class MoyKlass2 extends MoyKlass {
    
    private String pole3;
    
    public String getPole3(){
        return pole3;
    }
    
    public static class MoyKlass2Builder extends MoyKlass.MoyKlassBuilder{
        
        protected void init() {
            moyKlass = new MoyKlass2();
        }
        
        public static MoyKlass2Builder createMoyKlass2Builder(){
            return new MoyKlass2Builder();
        }
        
        public MoyKlass2Builder setPole3(String pole3){
            ((MoyKlass2)moyKlass).pole3 = pole3; // для новых полей преобразовуем ссылку на класс в MoyKlass2, поскольку moyKlass имеет тип MoyKlass
            return this;
        }
        
    }
}


Код

public class MoyKlassFactory {
    public static MoyKlass createMoyKlass1(String pole1, String pole2){
        return  MoyKlass.MoyKlassBuilder.createMoyKlassBuilder().setPole1(pole1).setPole2(pole2).build();
    }
    public static MoyKlass2 createMoyKlass2(String pole1, String pole2, String pole3){
        return (MoyKlass2) //прийдется явно преобразовывать, поскольку MoyKlassBuilder.build() возвращает не MoyKlass2, а MoyKlass
                            ((MoyKlass2Builder)MoyKlass2.MoyKlass2Builder.createMoyKlass2Builder().setPole1(pole1)
                                                                               .setPole2(pole2))//прийдется явно преобразовывать в MoyKlass2Builder
                                                                               //поскольку setPole2 возвращает MoyKlassBuilder, который не знает о новых сеттерах для полей
                                                                               .setPole3(pole3)
                                                                               .build();
    }
}


Код

public class Main {

    public static void main(String[] args) {
        MoyKlass moyKlass = MoyKlassFactory.createMoyKlass1("cp11", "cp12");
        System.out.println("Klass1 "+moyKlass.getPole1()+"|"+moyKlass.getPole2());
        MoyKlass2 moyKlass2 = MoyKlassFactory.createMoyKlass2("cp21", "cp22", "cp23");
        System.out.println("Klass2 "+moyKlass2.getPole1()+"|"+moyKlass2.getPole2()+"|"+moyKlass2.getPole3());
    }

}

PM MAIL ICQ   Вверх
math64
Дата 29.10.2009, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Код

public class Builder1<T extends Builder1> {
  T setA(Object a) { return (T)this; }
  Object build() { return null; }

  public static void main(String[] args) {
    Object o = new Builder1<Builder1>().setA("a").build();
  }
}

Код

public class Builder2 extends Builder1<Builder2> {
  Builder2 setB(Object b) { return this; }
  Object build() { return null; }

  public static void main(String[] args) {
    Object o = new Builder2().setA("a").setB("b").build();
  }
}

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1552 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.