Bài viết được sự cho phép của tác giả Giang Phan
Trong bài này, tôi sẽ giới thiệu với các bạn cách sử dụng một số tính năng mới trong Java 8 như Lambda , Function, Supplier, … để refactor code của một số Design Pattern.
Xem thêm nhiều việc làm Java lương cao trên TopDev
Refactoring Strategy Design Pattern
Strategy.java
package com.gpcoder.designpatterns.strategy; public interface Strategy { void performTask(); }
Strategy Pattern không sử dụng Lambda
StartegyPatternExample.java
package com.gpcoder.designpatterns.strategy; import java.util.Arrays; import java.util.List; class EagerStrategy implements Strategy { @Override public void performTask() { System.out.println("Eager strategy"); } } class LazyStratgey implements Strategy { @Override public void performTask() { System.out.println("Lazy strategy"); } } public class StartegyPatternExample { public static void main(String[] args) { Strategy eagerStrategy = new EagerStrategy(); Strategy lazyStrategy = new LazyStratgey(); List strategies = Arrays.asList(eagerStrategy, lazyStrategy); for (Strategy stg : strategies) { stg.performTask(); } } }
Strategy Pattern sử dụng Lambda
package com.gpcoder.designpatterns.strategy; import java.util.Arrays; import java.util.List; public class LambdaStartegyPatternExample { public static void main(String[] args) { Strategy eagerStrategy = () -> System.out.println("Eager strategy"); Strategy lazyStrategy = () -> System.out.println("Lazy strategy"); List strategies = Arrays.asList(eagerStrategy, lazyStrategy); strategies.forEach((elem) -> elem.performTask()); } }
Như bạn thấy, sử dụng Lambda code chúng ta đơn giản hơn nhiều, không cần tạo thêm các class.
Refactoring Observer Design Pattern
Observer.java
package com.gpcoder.designpatterns.observer; public interface Observer { void update(String str); }
Subject.java
package com.gpcoder.designpatterns.observer; public interface Subject { void registerObserver(Observer observer); void notifyObservers(String str); }
AccountService.java
package com.gpcoder.designpatterns.observer; import java.util.ArrayList; import java.util.List; public class AccountService implements Subject { private final List observers = new ArrayList<>(); public void login(String username) { System.out.println("Login: " + username); notifyObservers(username); } @Override public void registerObserver(Observer observer) { if (!observers.contains(observer)) { observers.add(observer); } } @Override public void notifyObservers(String str) { for (Observer observer : observers) { observer.update(str); } } }
Observer Pattern không sử dụng Lambda
package com.gpcoder.designpatterns.observer; class Logger implements Observer { @Override public void update(String str) { System.out.println("Logger: " + str); } } class Mailer implements Observer { @Override public void update(String str) { System.out.println("Mailer: " + str); } } public class ObserverPatternExample { public static void main(String[] args) { AccountService account = new AccountService(); // Register Observers account.registerObserver(new Logger()); account.registerObserver(new Mailer()); // Call service account.login("gpcoder"); } }
Observer Pattern sử dụng Lambda
package com.gpcoder.designpatterns.observer; public class LambdaObserverPatternExample { public static void main(String[] args) { AccountService account = new AccountService(); // Register Observers account.registerObserver(str -> System.out.println("Logger: " + str)); account.registerObserver(str -> System.out.println("Mailer: " + str)); // Call service account.login("gpcoder"); } }
Chạy 2 chương trình trên, ta có cùng kết quả:
Login: gpcoder Logger: gpcoder Mailer: gpcoder
Refactoring Chain of Responsibility Pattern
Filter.java
package com.gpcoder.designpatterns.chain; public abstract class Filter { private Filter nextFilter; public String doFilter(String str) { String result = handleString(str); if (nextFilter != null) { return nextFilter.doFilter(result); } return result; } public void setNextFilter(Filter nextFilter) { this.nextFilter = nextFilter; } protected abstract String handleString(String str); }
Chain of Responsibility Pattern không sử dụng Lambda
package com.gpcoder.designpatterns.chain; class Filter1 extends Filter { @Override protected String handleString(String str) { System.out.println("Filter1: " + str); return str + "->Filter1"; } } class Filter2 extends Filter { @Override protected String handleString(String str) { System.out.println("Filter2: " + str); return str + "->Filter2"; } } class Filter3 extends Filter { @Override protected String handleString(String str) { System.out.println("Filter3: " + str); return str + "->Filter3"; } } class AppFilter { public static Filter getFilter() { Filter1 filter1 = new Filter1(); Filter2 filter2 = new Filter2(); Filter3 filter3 = new Filter3(); filter1.setNextFilter(filter2); filter2.setNextFilter(filter3); return filter1; } } public class ChainOfResponsibilityExample { public static void main(String[] args) { // Build the chain of responsibility Filter filter = AppFilter.getFilter(); // Execute filter String result = filter.doFilter("gpcoder"); System.out.println("Final data: " + result); } }
Chain of Responsibility Pattern sử dụng Lambda và Function
package com.gpcoder.designpatterns.chain; import java.util.function.Function; import java.util.function.UnaryOperator; public class LamdaChainOfResponsibilityExample { public static void main(String[] args) { UnaryOperator filter1 = (str) -> { System.out.println("Filter1: " + str); return str + "->Filter1"; }; UnaryOperator filter2 = (str) -> { System.out.println("Filter2: " + str); return str + "->Filter2"; }; UnaryOperator filter3 = (str) -> { System.out.println("Filter3: " + str); return str + "->Filter3"; }; // Compose all functions resulting in a chain of operations. Function<String, String> appFilter = filter1.andThen(filter2).andThen(filter3); String result = appFilter.apply("gpcoder"); System.out.println("Final data: " + result); } }
Lưu ý: UnaryOperator là một Function, có cùng kiểu dữ liệu đầu vào và đầu ra. UnaryOperator<String> tương đương với cách viết Function<String, String>.
Chạy 2 chương trình trên, chúng ta có cùng kết quả:
Filter1: gpcoder Filter2: gpcoder->Filter1 Filter3: gpcoder->Filter1->Filter2 Final data: gpcoder->Filter1->Filter2->Filter3
Refactoring Factory Method Design Pattern
Bank.java
package com.gpcoder.designpatterns.factory; public interface Bank { String getBankName(); }
TPBank.java
package com.gpcoder.designpatterns.factory; public class TPBank implements Bank { @Override public String getBankName() { return "TPBank"; } }
VietcomBank.java
package com.gpcoder.designpatterns.factory; public class VietcomBank implements Bank { @Override public String getBankName() { return "VietcomBank"; } }
BankType.java
package com.gpcoder.designpatterns.factory; public enum BankType { VIETCOMBANK, TPBANK; }
Factory Method Pattern không sử dụng Java 8
package com.gpcoder.designpatterns.factory; class BankFactory { public static final Bank getBank(BankType bankType) { switch (bankType) { case TPBANK: return new TPBank(); case VIETCOMBANK: return new VietcomBank(); default: throw new IllegalArgumentException("This bank type is unsupported"); } } } public class FactoryMethodExample { public static void main(String[] args) { Bank bank = BankFactory.getBank(BankType.TPBANK); System.out.println(bank.getBankName()); // TPBank } }
Factory Method Pattern sử dụng Supplier và Method Reference
package com.gpcoder.designpatterns.factory; import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; class Java8BankFactory { private final static Map<BankType, Supplier> map = new HashMap<>(); static { map.put(BankType.TPBANK, TPBank::new); map.put(BankType.VIETCOMBANK, VietcomBank::new); } public static final Bank getBank(BankType bankType) { Supplier bank = map.get(bankType); if (bank == null) { throw new IllegalArgumentException("This bank type is unsupported"); } return bank.get(); } } public class Java8FactoryMethodExample { public static void main(String[] args) { Bank bank = Java8BankFactory.getBank(BankType.TPBANK); System.out.println(bank.getBankName()); // TPBank } }
Java 8 mang đến cho chúng ta rất nhiều tiện ích, các bạn hãy thử refactor code của mình sang Java 8 để code được gọn ràng hơn.
Bài viết gốc được đăng tải tại gpcoder.com
Có thể bạn quan tâm:
- Các loại Design patterns
- Một cách phân tích sử dụng design pattern trong C++
- Architectural Styles vs. Architectural Patterns vs. Design Patterns
Xem thêm tuyển dụng công nghệ thông tin hấp dẫn trên TopDev