Strategy Ne Değildir
Strategy ana algoritmayı gerçekleştiren sınıftan kalıtım değildir! Bu anlayış tamamen yanlış.
Kalıtım varsa bunun ismi Template Method Örüntüsüdür. Strategy ana algoritmayı gerçekleştiren sınıfa takılan davranıştır. Açıklaması şöyle.
Strategy ile tanımlanan arayüze uygun, farklı davranışlar gerçekleştiren sınıflar yazılır. Ve bu sınıflar ana algoritmayı çağıran sınıfa takılırlar. Strategy sınıfları genellikle bir Factory aracılığıyla yaratılır.
Strategy ana algoritmayı gerçekleştiren sınıftan kalıtım değildir! Bu anlayış tamamen yanlış.
Kalıtım varsa bunun ismi Template Method Örüntüsüdür. Strategy ana algoritmayı gerçekleştiren sınıfa takılan davranıştır. Açıklaması şöyle.
Imagine you design a Cache. The cache can have options regardingStrategy Nedir
- eviction policy (LIFO, FIFO, LRU)
- expiration policy (after read, after write)
- maximum size (number of elements, memory usage)
Now imagine you want to let the user of your cache choose any of these options, and you use inheritance. You'll need 3 * 2 * 2 = 12 different classes:
- LifoAfterReadNumberOfElementsBasedCache,
- LifoAfterReadMemoryBasedCache,
- etc.
Each of the 4 LifoXxx classes will have to implement the same algorithm to implement the LIFO strategy. Same for the other ones.
Implement it with the strategy pattern instead of inheritance, and you'll have a single Cache class, and 7 strategy classes (one for each strategy), that you can combine however you want, and without code duplication.
Strategy ile tanımlanan arayüze uygun, farklı davranışlar gerçekleştiren sınıflar yazılır. Ve bu sınıflar ana algoritmayı çağıran sınıfa takılırlar. Strategy sınıfları genellikle bir Factory aracılığıyla yaratılır.
Stategy'lerin Parameterik Olması
Örnek
Elimizde şöyle bir kod olsun
Çözüm 1
Şöyle yaparız. Her strategy kendi değerini kelvin'e veya başka ortak bir değere çevirir. Ana sınıf bu değerden okur.
Şöyle yaparız. Belki de strategy kullanmaya gerek bile yoktur. Her sınıf kullandığı birimi bilir. Geri kalan her şey parametriktir :)
Örnek - Sadece Enum Kullanmak
Örnek
Elimizde şöyle bir kod olsun
public abstract class Temperature {
  public abstract double convert(Temperature to) throws AbsoluteZeroException;
}public class Celsius extends Temperature {
  @Override
  public double convert(Temperature to) {
    ...
  }
}public class Fahrenheit extends Temperature {
 
  @Override
  public double convert(Temperature to) throws AbsoluteZeroException {
    ...
  }
}Çözüm 1
Şöyle yaparız. Her strategy kendi değerini kelvin'e veya başka ortak bir değere çevirir. Ana sınıf bu değerden okur.
public static Temperature convert(Temperature from, TemperatureScale to) {
  double kelvin = from.toKelvin();
  return to.fromKelvin(kelvin);
}Şöyle yaparız. Belki de strategy kullanmaya gerek bile yoktur. Her sınıf kullandığı birimi bilir. Geri kalan her şey parametriktir :)
Tempature celcius = new Tempature(98.6, TempatureType.CELSIUS);
Tempature fahrenheit = Tempature.convert(tempatureCels, TempatureType.FAHRENHEIT);Örnek - Sadece Enum Kullanmak
Şöyle yaparız
public enum FileType {
  EXCEL(".xlsx") {
    @Override
    public void download() {
    }
  },
  CSV(".csv") {
    @Override
    public void download() {
    }
  },
  private String suffix;
  FileType(String suffix) {
    this.suffix = suffix;
  }
  public String getSuffix() {
    return suffix;
  }
  public abstract void download();
}
@GetMapping("/exportOrderRecords")
public void downloadFile(User user, HttpServletResponse response) {
  ...
  String fileType = user.getFileType();
  FileType type = FileType.valueOf(fileType);
  if (type!=null) {
    type.download();
  } else {
    FileType.CSV.download();
  }
}Örnek - EnumMap
Burada yine bir Strategy arayüzü var ve her strategy kalıtımı için de bir Enum var. Aşağıdaki gibi Strategy sınıfları olsun
public interface class IStrategy {
}
public class DistanceStrategy implements IStrategy {
}
public class PowerStrategy implements IStrategy {
}
Bu sınıflar stateless ise Java'da EnumMap başka dillerde ise herhangi bir Map veri yapısına önceden doldurulurlar ve istenilince döndürülürler
GoF - Strategy Örüntüsü - Functional Java yazısına taşıdım
enum DataPresenterStrategyType { DISTANCE, POWER }
static EnumMap<DataPresenterStrategyType, IStrategy> lookupStrategy = new EnumMap();
{
  lookupStrategy.put(DISTANCE, new DistanceStrategy());
  lookupStrategy.put(POWER, new PowerStrategy());
}
DataPresenterStrategy toStrategy(StrategyType type) {
  return lookupStrategy.get(type);
}enum DataPresenterStrategyType { 
  DISTANCE(DistanceStrategy::new), POWER(PowerStrategy::new);
  private final Supplier<DataPresenterStrategy> constructor;
  DataPresenterStrategyType(Supplier<DataPresenterStrategy> constructor){
    this.constructor = constructor;
  }
  DataPresenterStrategy newStrategy() {
    return constructor.get();
  }
}GoF - Strategy Örüntüsü - Functional Java yazısına taşıdım
Strategy ve Dependency Injection
Aynı anda Etkin Birden Fazla Strategy'e Sahip Olmak
Normalde strategylerden sadece bir tanesi etkindir. Her strategy birbiriyle yer değiştirebilen nesne anlamına gelir. Bir nesneye farklı roller eklenebiliyorsa her role strategy demek yanlıştır. Nesneye bir çok rol çalışma zamanında eklenip çıkarılabilir. Bu durumda Decorator Örüntüsüne başvurmak gerekir.
 
 
Hiç yorum yok:
Yorum Gönder