Zmieniające się strategie i Spring

0

bangerska nutka na początek i tak:

public interface IRunnerStrategy {
	int nextStep(int currentStep);
}

do tego jakieś strategie przykładowo:

import org.springframework.stereotype.Component;

@Component
public class RunFast implements IRunnerStrategy {
	@Override
	public int nextStep(int currentStep) {
		return currentStep + 5;
	}
}
import org.springframework.stereotype.Component;

@Component
//@Primary - jezeli w Runnerze chce @Autowired
public class Walk implements IRunnerStrategy {
	@Override
	public int nextStep(int currentStep) {
		return currentStep + 1;
	}
}

Runner przyjmujący te strategie ( walk - domyślna):

import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Runner {

	@Value("0")
	private int currentStep;

	@Resource(name = "walk")
	private IRunnerStrategy runnerStrategy;

	public void nextStep() {
		currentStep += runnerStrategy.nextStep(currentStep);
	}

	public int getCurrentStep() {
		return currentStep;
	}

	public void setRunnerStrategy(IRunnerStrategy runnerStrategy) {
		this.runnerStrategy = runnerStrategy;
	}
}

przykładowy obiekt korzystający z Runnera, któremu zmienia strategie

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;

@Component
public class Example {

	@Autowired
	private Runner runner;

	@Resource(name = "walk")
	private IRunnerStrategy walk;

	@Resource(name = "runFast")
	private IRunnerStrategy runFast;

	//itd... tak musze ze wszystkimi strategiami eh ;.

	public void start() {
		System.out.println(runner.getCurrentStep());
		runner.nextStep();
		System.out.println(runner.getCurrentStep());
		runner.setRunnerStrategy(runFast);  //ZMIANA STRATEGII !!
		runner.nextStep();
		System.out.println(runner.getCurrentStep());
	}
}

Wcześniej ustawianie strategii było np. new runFast() teraz mam jako beany. Działa, ale czy to prawidłowe podejście (skoro mogę korzystać z Springa) ;] ? To przykład hipotetyczny, ale odzwierciedlający mój rzeczywisty problem.

1

To zależy. Czy ktoś jeszcze korzysta z tych beanów? Bo jeśli wstrzykujesz je tylko w jedno miejsce to ich sens jest taki-sobie. Poza tym ten twój kod nie wygląda specjalnie na podatny na łatwą rekonfiguracje, co znów trochę wypacza zabawę w beany. Bo gdybyś miała to xmlem na przykład zrobione tak, że user może sobie "skonfigurować" aplikację ustawiając czy chce taką albo inną strategię to co innego.

0

Ehh czyli nie ma sensu, bo z tych beanów-strategii żaden obiekt już więcej nie korzysta ;. No dobra to by było na tyle. tak tak normalnie mam xml, adnotacje tutaj były tylko żeby było lepiej widać ocb. Dzięki

1

Nie nie, generalnie adnotacje są spoko, ale trzeba wiedzieć gdzie co użyć ;) Jak masz jakieś serwisy które wstrzykujesz w aplikacji albo jakieś Dao to adnotacje są w porządku. Ale jak chcesz zrobić jakiś taki łatwo rekonfigurowalny obiekt to wtedy takie wstrzykiwanie z wpisywaniem z palca nazwy beana trochę to wypacza.

0

Rozumiem, no na stackoverflow czy nawet w PL jest trochę porad (kiedy lepiej adnotacje, kiedy xml) to bd musiała na to w końcu zerknąć.

1

Springa jako takiego jeszcze nie używałem, więc odpowiadam na podstawie innych "strzykawek":

Jeśli zawsze potrzebowałabyś dwóch strategii to można tak pewnie:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
 
@Component
public class Example {
 
    @Autowired
    private Runner runner;
 
    @Resource(name = "step1")
    private IRunnerStrategy step1;
 
    @Resource(name = "step2")
    private IRunnerStrategy step2;
 
    public void start() {
        runner.setRunnerStrategy(step1);  
        System.out.println(runner.getCurrentStep());
        runner.nextStep();
        System.out.println(runner.getCurrentStep());
        runner.setRunnerStrategy(step2);  
        runner.nextStep();
        System.out.println(runner.getCurrentStep());
    }
}

A w konfiguracji (XML?) powiązać nazwy "stepN" z konkretnymi implementacjami.

Ew. jeśli liczba strategii ma być zmienna po stronie wywołującej to można użyć wstrzykiwanej fabryki:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
 
@Component
public class Example {
 
    @Autowired
    private Runner runner;
 
    @Resource(name = "stepFactrory")
    private IRunnerFactory stepFactory;
 
    public void start() {
        runner.setRunnerStrategy(stepFactory.getStep("walk"));  
        System.out.println(runner.getCurrentStep());
        runner.nextStep();
        System.out.println(runner.getCurrentStep());
        runner.setRunnerStrategy(stepFactory.getStep("runFast"));  
        runner.nextStep();
        System.out.println(runner.getCurrentStep());
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1