0x01 什么是Monads
簡單說,Monad就是一種設(shè)計模式甜无,表示將一個運算過程瓣铣,通過函數(shù)拆解成互相連接的多個步驟。你只要提供下一步運算所需的函數(shù)津辩,整個運算就會自動進行下去。
下面這兩篇文章通過圖解的方式講解了什么是Monads
0x02 為什么要使用Monads容劳?
一段不優(yōu)雅的例子
編程時檢查參數(shù)是否為null是最常見的功能喘沿。以下面的代碼為例子:
public static class Userdetails{
public Address address;
public Name name;
}
public static class Name{
public String firstName;
public String lastName;
}
public static class Address{
public String houseNumber;
public Street street;
public City city;
}
public static class Street{
public String name;
}
public static class City{
public String name;
}
現(xiàn)在我想獲得
user.address.street.name
,常見代碼如下:
if(user == null )
return null;
else if(user.address == null)
return null;
else if(user.address.street == null)
return null;
else
return user.address.street.name;
這段檢測代碼淹沒了真正取值的代碼竭贩,閱讀性非常不優(yōu)雅
使用Monads來實現(xiàn)的例子
為了使用Lambda表達(dá)式蚜印,先定義一個函數(shù)接口:
SingleArgExpression
package function;
/**
* Created by haicheng.lhc on 13/04/2017.
*
* @author haicheng.lhc
* @date 2017/04/13
*/
@FunctionalInterface
public interface SingleArgExpression<P, R> {
public R function(P param);
}
然后創(chuàng)建一個類:
Option
package function;
import java.lang.reflect.ParameterizedType;
/**
* Created by haicheng.lhc on 13/04/2017.
*
* @author haicheng.lhc
* @date 2017/04/13
*/
public class Option<T> {
T value;
public Option(T value) {
this.value = value;
}
public <E> Option<E> flatMap(SingleArgExpression<T, Option<E>> mapper) {
if (value == null) {
return new Option<E>(null);
}
return mapper.function(value);
}
@Override
public boolean equals(Object rhs) {
if (rhs instanceof Option) {
Option o = (Option) rhs;
if (value == null) {
return (o.value == null);
} else {
return value.equals(o.value);
}
} else {
return false;
}
}
@Override
public int hashCode() {
return value == null ? 0 : value.hashCode();
}
public T get() {
System.out.println("hello");
return value;
}
}
接下來創(chuàng)建我們的測試類:
OptionExample
package function;
/**
* Created by haicheng.lhc on 13/04/2017.
*
* @author haicheng.lhc
* @date 2017/04/13
*/
public class OptionExample {
public static class Userdetails {
public Option<Address> address = new Option<>(null);
public Option<Name> name = new Option<>(null);
}
public static class Name {
public Option<String> firstName = new Option<String>(null);
public Option<String> lastName = new Option<String>(null);
}
public static class Address {
public Option<String> houseNumber;
public Option<Street> street;
public Option<City> city;
}
public static class Street {
public Option<String> name = new Option<>("alibaba");
}
public static class City {
public Option<String> name;
}
public static void main(String[] args) {
Option<Userdetails> userOpt = new Option<Userdetails>(new Userdetails());
//And look how simple it is now
String streetName = userOpt.flatMap(user -> user.address)
.flatMap(address1 -> address1.street)
.flatMap(street -> street.name)
.get();
System.out.println(streetName);
}
}
可以看出,通過這個方法獲取
user.address.street.name
的時候留量,代碼是非常簡潔易懂的窄赋。
思路解析:
create a class Option that represents an optional value. And lets then have a map method that will run a lambda on its wrapped value and return another option. If the wrapped value is null, it will return an Option containing null without processing the lambda, thus avaoiding a null pointer exception