8.2.1 策略模式
策略模式代表了解决一类算法的通用解决方案,你可以在运行时选择使用哪种方案。
策略模式包含三部分 :
- 一个代表某个算法的接口。
- 一个或多个该接口的具体实现,它们代表了算法的多种实现。
- 一个或多个使用策略对象的客户。
这里是传统的写法
// 策略模式的接口
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 观察者模式
某些事件发生时(比如状态改变),如果一个对象(通常称为主题)需要自动地通知其他多个对象(观察者)。
首先需要一个观察者接口,它将不同的观察者聚合在一起。
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);
}
现在可以通过实现这个抽象类来使用这一设计模式。
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