設計模式是前人開發經驗的總結,但是隨着Java語言的發展,很多設計模式有了新的表達方式。
尤其是Lambda表達式的出現。下面介紹幾種使用Lambda重構的設計模式 。
策略模式,模板方法,觀察者模式,責任鏈模式,工廠模式。
策略模式
策略模式 簡言之:一個接口,多種實現。使用時進行選擇。
不使用Lambda重構
public interface ValidationStrategy {
boolean execute(String s);
}
public class IsAllLowerCase implements ValidationStrategy {
@Override
public boolean execute(String s) {
return s.matches("[a-z]+");
}
}
public class IsNumeric implements ValidationStrategy {
@Override
public boolean execute(String s) {
return s.matches("\\d+");
}
}
public class Validator {
private final ValidationStrategy strategy;
public Validator(ValidationStrategy strategy) {
this.strategy = strategy;
}
public boolean validate(String s) {
return strategy.execute(s);
}
public static void main(String[] args) {
Validator numValidator = new Validator(new IsNumeric());
numValidator.validate("aaaa");
}
}
使用Lambda重構後:
@FunctionalInterface
public interface ValidationStrategy {
boolean execute(String s);
}
public class Validator {
private final ValidationStrategy strategy;
public Validator(ValidationStrategy strategy) {
this.strategy = strategy;
}
public boolean validate(String s) {
return strategy.execute(s);
}
public static void main(String[] args) {
boolean validate = new Validator(s -> s.matches("[a-z]+")).validate("aaaa");
}
}
模板方法
基於抽象方法,在抽象類實現 詳見本博客:https://my.oschina.net/u/3418748/blog/1617291
/**
* 在線銀行
*/
abstract class OnlineBanking{
/**
* 模板方法
*/
public processCustomer(int id){
Customer c = Datebase.getCustomerWithID(id);
makeCustomerHappy(c);
}
/**
* 讓上帝爽
*/
abstract void makeCustomerHappy(Customer c );
}
使用Lambda重構後:
/**
* 在線銀行
*/
@Service
public class OnlineBanking{
/**
* 模板方法
*/
public processCustomer(int id,Consumer<Customer> makeCustomerHappy){
Customer c = Datebase.getCustomerWithID(id);
makeCustomerHappy.accept(c);
}
}
// 使用方式
public class Test{
@Autowried
OnlineBanking onlineBanking;
public void test{
onlineBanking.processCustomer(123,(Consumer c) -> {
// 做一些羞羞的事
})
}
}
觀察者模式
不使用Lambda表達且最簡單一種實現
public interface Observer {
void notify(String tweet);
}
/**
* 《紐約時報》
*
* @author lien6o
*
*/
public class NYTimes implements Observer {
@Override
public void notify(String tweet) {
if (tweet != null && tweet.contains("money")) {
System.err.println("Breaking news in NY" + tweet);
}
}
}
/**
* 《衛報》
*
* @author lien6o
*
*/
public class Guardian implements Observer {
@Override
public void notify(String tweet) {
if (tweet != null && tweet.contains("queen")) {
System.err.println("Yet another news in London..." + tweet);
}
}
}
public interface Subject {
void registerObserver(Observer o);
void notifyObserver(String tweet);
}
public class Feed implements Subject {
private final List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer o) {
this.observers.add(o);
}
@Override
public void notifyObserver(String tweet) {
this.observers.forEach(o -> o.notify(tweet));
}
public static void main(String[] args) {
Feed feed = new Feed();
feed.registerObserver(new NYTimes());
feed.registerObserver(new Guardian());
feed.notifyObserver("The queen says her favorite blog is the one you see");
}
}
使用Lambda表達式後
// 有沒有這個函數接口聲明都能使用 我只是爲了體現 它的函數接口特性
@FunctionalInterface
public interface Observer {
void notify(String tweet);
}
public class Feed implements Subject {
private final List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer o) {
this.observers.add(o);
}
@Override
public void notifyObserver(String tweet) {
this.observers.forEach(o -> o.notify(tweet));
}
public static void main(String[] args) {
Feed feed = new Feed();
// 取消了Observer的實現類 在使用時直接使用
// 簡單實現可以在用lambda表達式這樣使用,複雜的不建議這樣操作,不能解耦。反而適得其反
feed.registerObserver(tweet -> {
if (tweet != null && tweet.contains("money")) {
System.err.println("Breaking news in NY" + tweet);
}
});
feed.notifyObserver("The queen says her favorite blog is the one you see");
}
}
個人感覺在觀察者模式使用意義不大。
責任鏈模式
這種模式是通過定義一個代表處理對象的抽象類來具體實現的,在抽象類中會定義一個字段來記錄後續對象。一旦對象完成它的工作,處理對象就會將它的工作換交給它的後繼。
public abstract class ProcessingObject<T> {
protected ProcessingObject<T> successor;
public void setSeccessor(ProcessingObject<T> successor) {
this.successor = successor;
}
abstract protected T handleWork(T input);
public T handle(T input) {
T r = handleWork(input);
if (successor != null) {
return successor.handle(r);
}
return r;
}
}
public class HeaderTextProcessing extends ProcessingObject<String> {
@Override
protected String handleWork(String text) {
return "From Raoul,Mario and Alan:" + text;
}
}
public class SpellCkeckerProcessing extends ProcessingObject<String> {
@Override
protected String handleWork(String text) {
return text.replace("labda", "lambda");
}
}
public static void main(String[] args) {
HeaderTextProcessing p1 = new HeaderTextProcessing();
SpellCkeckerProcessing p2 = new SpellCkeckerProcessing();
p1.setSeccessor(p2);
String handle = p1.handle("Aren't labdas readlly sexy!!");
System.err.println(handle);
}
使用Lambda表達式
public static void main(String[] args) {
// UnaryOperator t -> t; 一元表達式
UnaryOperator<String> p1 = text -> "From Raoul,Mario and Alan:" + text;
UnaryOperator<String> p2 = text -> text.replace("labda", "lambda");
// andThen() return (T t) -> after.apply(apply(t))
Function<String, String> pipeline = p1.andThen(p2);
String result = pipeline.apply("Aren't labdas readlly sexy!!");
System.err.println(result);
}
使用Lambda構造鏈接。很贊!
工廠模式
public static Product createProduct(String name) {
switch (name) {
case "loan":
return new Loan();
case "stock":
return new Stock();
default:
throw new RuntimeException("No such product " + name);
}
}
public static void main(String[] args) {
Stock stock = (Stock) ProductFactory.createProduct("stock");
}
使用Lambda表達式
final static Map<String, Supplier<Product>> map = new HashMap<>();
static {
map.put("loan", Loan::new);
map.put("stock", Stock::new);
}
public static void main(String[] args) {
Product product = map.get("loan").get();
}
重構後對於簡單參數映射對象使用lambda還不錯,但是多個參數lambda擴展性不強,其實剛開始寫代碼用這種模式寫不利於擴展。