JDK1.8 使用Lambda重構設計模式

設計模式是前人開發經驗的總結,但是隨着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擴展性不強,其實剛開始寫代碼用這種模式寫不利於擴展。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章