Lambda를 이용하여 기존 디자인패턴을 변경해보기
from Java 8 In Action
1. 전략패턴
1.1 일반적인 전략패턴 개발방식
public interface ValidationStrategy {boolean execute(String s);
}
public class IsAllowerCase implements ValidationStrategy {
public boolean execute(String s) {
return s.match("[a-z]+");
}
}
public class IsNumeric implements ValidationStrategy {
public boolean execute(String s) {
return s.matches("\\d+");
}
}
public class Validator {
private final ValidationStrategy strategy;
public Validator(ValidationStrategy v) {
this.strategy = v;
}
public boolean validate(String s) {
return strategy.execute(s);
}
}
Validator numericValidator = new Validator(new IsNumeric());
boolean b1 = numericValidator.validate("aaa");
Validator lowerCaseValidator = new Validator(new IsAllLowerCase());
boolean b2 = lowerCaseValidator.validate("bbb");
1.2 람다를 이용한 개발 방식
Validator numericValidator = new Validator((String s) -> s.matches("[a-z]+"));boolean b1 = numericValidator.validate("aaa");
Validator lowerCaseValidator = new Validator((String a) -> s.match("\\d+"));
boolean b2 = lowerCaseValidator.validate("bbb");
2. Template Method
2.1 일반적인 템플릿 메소드 방식
abstract class OnlineBanking {
public void processCustomer(int id) {
Customer c = Database.getCustomerWithId(id);
makeCustomerHappy(c);
}
abstract void makeCustomerHappy(Customer c);
}
2.2 람다를 이용한 개발 방식
public void processCustomer(int id, Consumer<Customer> makeCustomerHappy) {Customer c = Database.getCustomerWithId(id);
makeCustomerHappy.accept(c);
}
new OnlineBankingLambda().processCustomer(1234, (Customer c) -> System.out.println("Hello " + c.getName()));
3. Observer
3.1 일반적인 옵저버 패턴
interface Observer {void notify(String tweet);
}
class NYTimes implements Observer {
public void notify(String tweet) {
if (tweet != null && tweet.contains("money")) {
System.out.println("Breaking news in NY! " + tweet);
}
}
}
class Guardian implements Observer {
public void notify(String tweet) {
if (tweet != null && tweet.contain("queen")) {
System.out.println("Yet another news in London... " + tweet);
}
}
}
class LeMonde implements Observer {
public void notify(String tweet) {
if (tweet != null && tweet.contains("wine")) {
System.out.println("Today cheese, wine and news! " + tweet);
}
}
}
interface Subject {
void registerObserver(Observer o);
void notifyObservers(String tweet);
}
class Feed implements Subject {
private final List<Observer> observers = new ArrayList<>();
public void registerObserver(Observer o) {
this.observers.add(o);
}
public void notifyObservers(String tweet) {
observers.forEach(o -> o.notify(tweet));
}
}
Feed f = new Feed();
f.registerObserver(new NYTimes());
f.registerObserver(new Guardian());
f.registerObserver(new LeMonde());
f.notifyObservers("The queen said her favorite book is Java 8 in Action");
3.2 람다 방식의 개발
f.registerObserver((String tweet) -> {if (tweet != null && tweet.contains("money")) {
System.out.println("Breaking news in NY! " + tweet);
}
});
f.registerObserver((String tweet) -> {
if (tweet != null && tweet.contains("queen")) {
System.out.println("Yet another news in London... " + tweet);
}
});
4. Chain of Responsibility
4.1 일반적인 방식의 COR방식
public abstract class ProcessingObject<T> {protected ProcessingObject<T> successor;
public void setSucessor(ProcessingObject<T> successor) {
this.successor = successor;
}
public T handle(T input) {
T r = handleWork(input);
if (successor != null) {
return successor.handle(r);
}
return r;
}
abstract protected T handleWork(T input);
}
public class HeaderTextProcessing extends ProcessingObject<String> {
public String handleWork(String text) {
return "From Raoul, Mario and Alan: " + text;
}
}
public class SpellCheckerProcessing extends ProcessingObject<String> {
public String handleWork(String text) {
return text.replaceAll("labda", "lambda");
}
}
ProcessingObject<String> p1 = new HeaderTextProcessing();
ProcessingObject<String> p2 = new SpellCheckerProcessing();
p1.setSuccessor(p2);
String result = p1.handle("Aren't labdas really sexy?!!");
System.out.println(result);
4.2 람다 방식
UnaryOperator<String> headerProcessing = (String text) -> "From Raoul, Mario and Alan: " + text;UnaryOperator<String> spellCheckerProcessing = (String text) -> text.replaceAll("labda", "lambda");
Function<String, String> pipeline = handleProcessing.andThen(spellCheckerProcessing);
String result = pipeline.apply("Aren't labdas really sexy?!!");
5. Factory
5.1 일반적인 팩토리
public class ProductFactory{public static Product createProduct(String name) {
switch(name) {
case "loan":
return new Loan();
case "stock":
return new Stock();
case "bond":
return new Bond();
default:
throws new RuntimeException("No such product " + name);
}
}
}
Product p = ProductFactory.createProduct("loan");
5.2 람다 방식
Supplier<Product> loanSupplier = Lona::new;Loan loan = loanSupplier.get();
final static Map<String, Supplier<Product>> map = new HashMap<>();
static {
map.put("loan", Loan::new);
map.put("stock", Stock::new);
map.put("bond", Bond::new);
}
public static Product createProduct(String name) {
Suppler<Product> p = map.get(name);
if (p != null) return p.get();
throw new IllegalArgumentException("No Such product " + name);
}