Bootstrap

8.2 使用Lambda重构面向对象的设计模式


8.2.1 策略模式


策略模式代表了解决一类算法的通用解决方案,你可以在运行时选择使用哪种方案。
策略模式包含三部分 :

  • 一个代表某个算法的接口。
  • 一个或多个该接口的具体实现,它们代表了算法的多种实现。
  • 一个或多个使用策略对象的客户。
    ![[Pasted image 20241204103605.png]]

这里是传统的写法

// 策略模式的接口  
interface ConversionString {  
    String convert(String s);  
}  
// 具体的实现  
class Strategy1 implements ConversionString {  
    @Override  
    public String convert(String s) {  
        return s.toLowerCase();  
    }  
}  
class Strategy2 implements ConversionString {  
    @Override  
    public String convert(String s) {  
        return s.toUpperCase();  
    }  
}  
// class Conversion {  
    private ConversionString conversionString;  
  
    public String convert(String s) {  
        return conversionString.convert(s);  
    }  
    public Conversion(ConversionString conversionString) {  
        this.conversionString = conversionString;  
    }  
}

System.out.println(new Conversion(new Strategy1()).convert("Hello World"));  
System.out.println(new Conversion(new Strategy2()).convert("Hello World"));
输出 : 
hello world
HELLO WORLD

直接使用Lambda表达式可以省去臃肿的实现类写法

System.out.println(new Conversion(s -> s.toLowerCase()).convert("Hello World"));  
System.out.println(new Conversion(s -> s.toUpperCase()).convert("Hello World"));
输出 : 
hello world
HELLO WORLD

8.2.2 模板方法


如果你需要采用某个算法的框架,同时又希望有一定的灵活度,能对它的某些部分进行改进,那么采用模板方法设计模式是比较通用的方案。

假设你需要编写一个简单的在线银行应用。通常,用户需要输入一个用户账户,之后应用才能从
银行的数据库中得到用户的详细信息,最终完成一些让用户满意的操作。不同分行的在线银行应用让客户满意的方式可能还略有不同。

abstract class OnlineBank {  
    class Customer {  
        public String name;  
        public int id;  
  
        public Customer(String name, int id) {  
            this.name = name;  
            this.id = id;  
        }  
    }  
    public List<Customer> customers = new ArrayList<Customer>();  
    public void processCustomer(int id) {  
        Customer customer = getCustomer(id);  
        makeCustomerHappy(customer);  
    }  
  
    public Customer getCustomer(int id) {  
        return customers.stream().filter(customer -> customer.id == id).findFirst().get();  
    }  
    abstract void makeCustomerHappy(Customer customer);  
}

现在对于不同的银行,只要继承OnlineBank类就可以实现不同的方法来让客户满意。
如果你稍微改下processCustomer方法,就可以在不继承OnlineBank的情况下实现这一功能。

public void processCustomer(int id, Consumer<Customer> consumer) {  
    Customer customer = getCustomer(id);  
    consumer.accept(customer);  
}

8.2.3 观察者模式


某些事件发生时(比如状态改变),如果一个对象(通常称为主题)需要自动地通知其他多个对象(观察者)。
![[Pasted image 20241204133149.png]]

首先需要一个观察者接口,它将不同的观察者聚合在一起。

interface Observer {  
    void notify(String tweet);  
}

可以通过实现接口来声明不同的观察者
这一看到实现接口,就知道又是Lambda了

class PeopleDaily implements Observer {  
    @Override  
    public void notify(String tweet) {  
        if (tweet.contains("people")) {  
            System.out.println("haha");  
        }  
    }  
}  
  
class KowloonDaily implements Observer {  
    @Override  
    public void notify(String tweet) {  
        if (tweet.contains("kowloon")) {  
            System.out.println("qudarf");  
        }  
    }  
}
interface Subject {  
    void registerObserver(Observer observer);  
    void notifyObservers(String tweet);  
}  
  
class Feed implements Subject {  
    // Feed 类的内部维护了一个观察者列表,当一条消息到来时会自动推送给列表中的每一个观察者  
    public final List<Observer> observers = new ArrayList<Observer>();  
    @Override  
    public void registerObserver(Observer observer) {  
        observers.add(observer);  
    }  
  
    @Override  
    public void notifyObservers(String tweet) {  
        observers.forEach(observer -> observer.notify(tweet));  
    }  
}

Lambda表达式究竟会放在哪呢,好难猜啊

feed.registerObserver(tweet -> {  
    if (tweet.contains("kowloon")) {  
        System.out.println("qudarf");  
    }  
});  
  
feed.registerObserver(tweet -> {  
    if (tweet.contains("kowloon")) {  
        System.out.println("qudarf");  
    }  
});

8.2.4 责任链模式


责任链模式是一种创建处理对象序列(比如操作序列)的通用方案。一个处理对象可能需要在完成一些工作之后,将结果传递给另一个对象,这个对象接着做一些工作,再转交给下一个处理对象,以此类推。

abstract class Processor<T> {  
    protected Processor<T> processor;  
  
    public Processor(Processor<T> processor) {  
        this.processor = processor;  
    }  
  
    public T handle(T input) {  
        T handleWork = handleWork(input);  
        if (processor != null) {  
            return processor.handle(handleWork);  
        }  
        return handleWork;  
    }  
  
    abstract protected T handleWork(T input);  
}

![[Pasted image 20241204140404.png]]

现在可以通过实现这个抽象类来使用这一设计模式。

abstract class Processor<T> {  
    protected Processor<T> processor;  
  
    public Processor() {  
    }  
    public Processor(Processor<T> processor) {  
        this.processor = processor;  
    }  
  
    public void setProcessor(Processor<T> processor) {  
        this.processor = processor;  
    }  
  
    public T handle(T input) {  
        T handleWork = handleWork(input);  
        if (processor != null) {  
            return processor.handle(handleWork);  
        }  
        return handleWork;  
    }  
  
    abstract protected T handleWork(T input);  
}

class HandleA extends Processor<String> {  
    @Override  
    protected String handleWork(String input) {  
        return input + " come back";  
    }  
}  
  
class HandleB extends Processor<String> {  
    @Override  
    protected String handleWork(String input) {  
        return "manba " + input;  
    }  
}

HandleA handleA = new HandleA();  
HandleB handleB = new HandleB();  
handleA.setProcessor(handleB);  
System.out.println(handleA.handle("What can I say"));
输出 : 
manba What can I say come back

之前有一个andThen方法可以实现这一功能。

UnaryOperator<String> handle1 = text -> "manba " + text;  
UnaryOperator<String> handle2 = text -> text + " come back";  
Function<String, String> pipeLine = handle1.andThen(handle2);  
System.out.println(pipeLine.apply("what can I say"));
输出 : 
manba what can I say come back

这里代码已经比较长了,截断一下吧

package lambdasinaction.chap8;  
  
import java.util.ArrayList;  
import java.util.List;  
import java.util.Locale;  
import java.util.function.Consumer;  
import java.util.function.Function;  
import java.util.function.UnaryOperator;  
  
// 策略模式的接口  
interface ConversionString {  
    String convert(String s);  
}  
// 具体的实现  
class Strategy1 implements ConversionString {  
    @Override  
    public String convert(String s) {  
        return s.toLowerCase();  
    }  
}  
class Strategy2 implements ConversionString {  
    @Override  
    public String convert(String s) {  
        return s.toUpperCase();  
    }  
}  
//  
class Conversion {  
    private ConversionString conversionString;  
  
    public String convert(String s) {  
        return conversionString.convert(s);  
    }  
    public Conversion(ConversionString conversionString) {  
        this.conversionString = conversionString;  
    }  
}  
  
abstract class OnlineBank {  
    class Customer {  
        public String name;  
        public int id;  
  
        public Customer(String name, int id) {  
            this.name = name;  
            this.id = id;  
        }  
    }  
    public List<Customer> customers = new ArrayList<Customer>();  
    public void processCustomer(int id) {  
        Customer customer = getCustomer(id);  
        makeCustomerHappy(customer);  
    }  
  
    public void processCustomer(int id, Consumer<Customer> consumer) {  
        Customer customer = getCustomer(id);  
        consumer.accept(customer);  
    }  
  
    public Customer getCustomer(int id) {  
        return customers.stream().filter(customer -> customer.id == id).findFirst().get();  
    }  
    abstract void makeCustomerHappy(Customer customer);  
}  
  
interface Observer {  
    void notify(String tweet);  
}  
  
class PeopleDaily implements Observer {  
    @Override  
    public void notify(String tweet) {  
        if (tweet.contains("people")) {  
            System.out.println("haha");  
        }  
    }  
}  
  
class KowloonDaily implements Observer {  
    @Override  
    public void notify(String tweet) {  
        if (tweet.contains("kowloon")) {  
            System.out.println("qudarf");  
        }  
    }  
}  
  
interface Subject {  
    void registerObserver(Observer observer);  
    void notifyObservers(String tweet);  
}  
  
class Feed implements Subject {  
    // Feed 类的内部维护了一个观察者列表,当一条消息到来时会自动推送给列表中的每一个观察者  
    public final List<Observer> observers = new ArrayList<Observer>();  
    @Override  
    public void registerObserver(Observer observer) {  
        observers.add(observer);  
    }  
  
    @Override  
    public void notifyObservers(String tweet) {  
        observers.forEach(observer -> observer.notify(tweet));  
    }  
}  
  
abstract class Processor<T> {  
    protected Processor<T> processor;  
  
    public Processor() {  
    }  
    public Processor(Processor<T> processor) {  
        this.processor = processor;  
    }  
  
    public void setProcessor(Processor<T> processor) {  
        this.processor = processor;  
    }  
  
    public T handle(T input) {  
        T handleWork = handleWork(input);  
        if (processor != null) {  
            return processor.handle(handleWork);  
        }  
        return handleWork;  
    }  
  
    abstract protected T handleWork(T input);  
}  
  
class HandleA extends Processor<String> {  
    @Override  
    protected String handleWork(String input) {  
        return input + " come back";  
    }  
}  
  
class HandleB extends Processor<String> {  
    @Override  
    protected String handleWork(String input) {  
        return "manba " + input;  
    }  
}  
  
public class Test02 {  
    public static void main(String[] args) {  
        System.out.println(new Conversion(new Strategy1()).convert("Hello World"));  
        System.out.println(new Conversion(new Strategy2()).convert("Hello World"));  
        System.out.println("================================");  
        System.out.println(new Conversion(s -> s.toLowerCase()).convert("Hello World"));  
        System.out.println(new Conversion(s -> s.toUpperCase()).convert("Hello World"));  
        System.out.println("================================");  
        Feed feed = new Feed();  
        feed.registerObserver(tweet -> {  
            if (tweet.contains("kowloon")) {  
                System.out.println("qudarf");  
            }  
        });  
  
        feed.registerObserver(tweet -> {  
            if (tweet.contains("kowloon")) {  
                System.out.println("qudarf");  
            }  
        });  
        System.out.println("================================");  
        HandleA handleA = new HandleA();  
        HandleB handleB = new HandleB();  
        handleA.setProcessor(handleB);  
        System.out.println(handleA.handle("What can I say"));  
        System.out.println("================================");  
        UnaryOperator<String> handle1 = text -> "manba " + text;  
        UnaryOperator<String> handle2 = text -> text + " come back";  
        Function<String, String> pipeLine = handle1.andThen(handle2);  
        System.out.println(pipeLine.apply("what can I say"));  
        System.out.println("================================");  
    }  
}
输出 : 
hello world
HELLO WORLD
================================
hello world
HELLO WORLD
================================
================================
manba What can I say come back
================================
manba what can I say come back
================================

8.2.5 工厂模式


使用工厂模式,你无需向客户暴露实例化的逻辑就能完成对象的创建。
下面是一个工厂类

package lambdasinaction.chap8;  
  
class Fruit {}  
class Apple extends Fruit {}  
class Orange extends Fruit {}  
class banana extends Fruit {}  
  
public class FruitFactory {  
    public static Fruit createFruit(String fruit) {  
        switch (fruit) {  
            case "Apple": return new Apple();  
            case "Orange": return new Orange();  
            case "Banana": return new banana();  
        }  
        return null;  
    }  
  
    public static void main(String[] args) {  
        Fruit fruit = createFruit("Apple");  
        System.out.println(fruit.getClass().getSimpleName());  
    }  
}
输出 : 
Apple

下面是一个更好的实现方式

package lambdasinaction.chap8;  
  
import java.util.HashMap;  
import java.util.Map;  
import java.util.function.Supplier;  
  
public class FruitFactory2 {  
    public static Map<String, Supplier<Fruit>> map = new HashMap<>();  
    static {  
        map.put("Apple", Apple::new);  
        map.put("Banana", Banana::new);  
        map.put("Organe", Orange::new);  
    }  
  
    public static Fruit createFruit(String fruit) {  
        return map.get(fruit).get();  
    }  
  
    public static void main(String[] args) {  
        Fruit apple = FruitFactory2.createFruit("Apple");  
        System.out.println(apple.getClass().getSimpleName());  
    }  
}
输出 :  
Apple
;