Реализация шаблона Hierarchical Builder

Я реализую шаблон Hierarchical Builder. Я использовал дженерики, чтобы сделать возвращаемый тип моего сеттера Parent Builder таким же, как для дочернего. Тем не менее, я сталкиваюсь с проблемой, когда использую метод дочернего установщика после вызова метода родительского установщика. Я не хочу определять свой дочерний метод (setEngine(String) здесь) в моем Parent Builder. Есть ли другой способ решить эту проблему?

Я сделал пример фрагмента для указанной проблемы, идентичный этому случаю.

CarFactory -› возвращает объект конкретного автомобиля, который хочет пользователь.

Автомобиль – Родитель для всех типов автомобилей, Swift, Duster и т. д.

Swift –› конкретный автомобиль

Иерархия «родительский-›дочерний»

Автомобиль -> Свифт

CarBuilder -> SwiftBuilder

Car.java

 package Builders;

 public class Car {
   int tyre;
   int seat;
   public int getTyre() {
       return tyre;
   }
   public void setTyre(int tyre) {
       this.tyre = tyre;
   }
   public int getSeat() {
       return seat;
   }
   public void setSeat(int seat) {
       this.seat = seat;
       
   }
   
}

Swift.java

package Builders;

public class Swift extends Car {
    boolean safetyAirbag;
    String engine;
    
    public boolean isSafetyAirbag() {
        return safetyAirbag;
    }

    public String getEngine() {
        return engine;
    }

    public void setSafetyAirbag(boolean safetyAirbag) {
        this.safetyAirbag = safetyAirbag;
    }

    public void setEngine(String engine) {
        this.engine = engine;
    }


}

CarBuilder.java

package Builders;

public abstract class CarBuilder {
        int tyre;
        int seat;
         
        public abstract <B extends CarBuilder>B self();
        public abstract <T extends Car>T typeOfCar();
            
        public <B extends CarBuilder>B setTyre(int tyre) {
            this.tyre = tyre;
            return self();
        }
        
        public  <B extends CarBuilder> B setSeat(int seat) {
            this.seat = seat;
            return self();
        }
        public <C extends Car>C build()
        {   C car=this.typeOfCar();
            car.setSeat(seat);
            car.setTyre(tyre);
            return car;
        }
    
        
}

SwiftBuilder.java

package Builders;

public class SwiftBuilder extends CarBuilder {
    String engine;
    @Override
    public
    SwiftBuilder self() {
        
        return this;
    }

    @Override
    public
    Swift typeOfCar() {
        
        return new Swift();
    }

    public SwiftBuilder setEngine(String string) {
        this.engine=string;
        return this;
    }
    public Swift build()
    {   Swift s=(Swift)super.build();
        return s;
    }

}

CarFactory.java

package Builders;

public class CarFactory {
    public SwiftBuilder getSwiftDesire()
    {
        return new SwiftBuilder();
    }
}
 

Драйверы.java

package Builders;

public class Drivers {
    Swift getMyCar() {
        Swift s= this.factory().getSwiftDesire().setSeat(4).setEngine("CC").build();
        return s;
    }
    CarFactory factory() {
        return new CarFactory();
    }
}

В классе Drivers.java я не могу использовать метод setEngine() после метода setSeat(), this.factory().getSwiftDesire().setSeat(4).setEngine(CC).build(); Я не хочу объявлять setEngine в родительском классе, есть ли способ обойти это?

Заранее спасибо!


person coderzzz18    schedule 17.03.2020    source источник


Ответы (1)


Вам нужно использовать дженерики на уровне класса, а не на уровне метода в вашем CarBuilder:

package Builders;

public abstract class CarBuilder<B extends CarBuilder<B, C>, C extends Car> {
    int tyre;
    int seat;

    public abstract B self();

    public abstract C typeOfCar();

    public B setTyre(int tyre) {
        this.tyre = tyre;
        return self();
    }

    public B setSeat(int seat) {
        this.seat = seat;
        return self();
    }

    public C build() {
        C car = this.typeOfCar();
        car.setSeat(seat);
        car.setTyre(tyre);
        return car;
    }

}

И затем вы определяете свой SwiftBuilder:

package Builders;

public class SwiftBuilder extends CarBuilder<SwiftBuilder, Swift> {
    String engine;

    @Override
    public SwiftBuilder self() {

        return this;
    }

    @Override
    public Swift typeOfCar() {

        return new Swift();
    }

    public SwiftBuilder setEngine(String string) {
        this.engine = string;
        return this;
    }

    public Swift build() {
        Swift s = super.build();
        return s;
    }

}

И это работает.

person Dmitry Pisklov    schedule 17.03.2020
comment
Это было потрясающе, это было то, что я искал! Познакомился с новой вещью в дженериках Java. Спасибо :) - person coderzzz18; 18.03.2020