Java8笔记4

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

 

1.观察者模式:

观察者模式是一种比较常见的方案,某些事件发生时(比如状态转变),如果一个对象(通 常我们称之为主题)需要自动地通知其他多个对象(称为观察者),就会采用该方案。

 

首先,你需要一个观察者接口,它将不同的观察者聚合在一起。它仅有一个名为 notify 的 方法,一旦接收到一条新的新闻,该方法就会被调用:
interface Observer { 
 void notify(String tweet); 
}
现在,你可以声明不同的观察者(比如,这里是三家不同的报纸机构),依据新闻中不同的 关键字分别定义不同的行为:
class NYTimes implements Observer{ 
 public void notify(String tweet) { 
 if(tweet != null && tweet.contains("money")){ 
 System.out.println("Breaking news in NY! " + tweet); 
 } 
 } 
} 
class Guardian implements Observer{ 
 public void notify(String tweet) { 
 if(tweet != null && tweet.contains("queen")){ 
 System.out.println("Yet another news in London... " + tweet); 
 } 
 } 
} 
class LeMonde implements Observer{ 
 public void notify(String tweet) { 
 if(tweet != null && tweet.contains("wine")){ 
 System.out.println("Today cheese, wine and news! " + tweet); 
 } 
 } 
}

主题接口:

interface Subject{ 
 void registerObserver(Observer o); 
 void notifyObservers(String tweet); 
}
       Subject 使用 registerObserver 方法可以注册一个新的观察者,使用 notifyObservers 方法通知它的观察者一个新闻的到来。让我们更进一步,实现Feed 类:
class Feed implements Subject{ 
 private final List<Observer> observers = new ArrayList<>(); 
 public void registerObserver(Observer o) { 
 this.observers.add(o); 
 } 
 public void notifyObservers(String tweet) { 
 observers.forEach(o -> o.notify(tweet)); 
 } 
}
这是一个非常直观的实现: Feed 类在内部维护了一个观察者列表,一条新闻到达时,它就 进行通知。
Feed f = new Feed(); 
f.registerObserver(new NYTimes()); 
f.registerObserver(new Guardian()); 
f.registerObserver(new LeMonde()); 
f.notifyObservers("today is 2020/5/14, plt had dead out");
使用 Lambda 表达式
       你可能会疑惑 Lambda 表达式在观察者设计模式中如何发挥它的作用。不知道你有没有注意
到, Observer 接口的所有实现类都提供了一个方法: notify 。新闻到达时,它们都只是对同一
段代码封装执行。 Lambda 表达式的设计初衷就是要消除这样的僵化代码。使用 Lambda 表达式后,
你无需显式地实例化三个观察者对象,直接传递 Lambda 表达式表示需要执行的行为即可:
f.registerObserver((String tweet) -> { 
 if(tweet != null && tweet.contains("money")){ 
 System.out.println("Breaking news in NY! " + tweet); 
 } 
}); 
f.registerObserver((String tweet) -> { 
 if(tweet != null && tweet.contains("queen")){ 
 System.out.println("Yet another news in London... " + tweet); 
 } 
});
        那么,是否我们随时随地都可以使用 Lambda 表达式呢?答案是否定的!我们前文介绍的例
子中, Lambda 适配得很好,那是因为需要执行的动作都很简单,因此才能很方便地消除僵化代
码。但是,观察者的逻辑有可能十分复杂,它们可能还持有状态,抑或定义了多个方法,诸如此
类。在这些情形下,你还是应该继续使用类的方式。
 
2.责任链模式:
       责任链模式是一种创建处理对象序列(比如操作序列)的通用方案。一个处理对象可能需要
在完成一些工作之后,将结果传递给另一个对象,这个对象接着做一些工作,再转交给下一个处
理对象,以此类推。
      通常,这种模式是通过定义一个代表处理对象的抽象类来实现的,在抽象类中会定义一个字
段来记录后续对象。一旦对象完成它的工作,处理对象就会将它的工作转交给它的后继。代码中,
这段逻辑看起来是下面这样:
public abstract class ProcessingObject<T> { 
 protected ProcessingObject<T> successor; 
 public void setSuccessor(ProcessingObject<T> successor){ 
 this.successor = successor;
} 
 public T handle(T input){ 
 T r = handleWork(input); 
 if(successor != null){ 
 return successor.handle(r); 
 } 
 return r; 
 } 
 abstract protected T handleWork(T input); 
}

 

其实这就是模板方法设计模式。 handle 方法提供了如何进行
工作处理的框架。不同的处理对象可以通过继承 ProcessingObject 类,提供 handleWork 方法
来进行创建。
public class HeaderTextProcessing extends ProcessingObject<String> { 
 public String handleWork(String text){ 
 return "From a, b and c: " + text; 
 } 
} 
public class SpellCheckerProcessing extends ProcessingObject<String> { 
 public String handleWork(String text){ 
 return text.replaceAll("abc", "bcd"); 
 } 
}
现在你就可以将这两个处理对象结合起来,构造一个操作序列
 
ProcessingObject<String> p2 = new SpellCheckerProcessing(); 
p1.setSuccessor(p2);
String result = p1.handle("Aren't abc really sexy?!!"); 
System.out.println(result);
输出:“From a, b and c:  Aren't bcd really sexy?!!”
 
使用 Lambda 表达式
UnaryOperator<String> headerProcessing = 
 (String text) -> "From a, b and c: " + text;
UnaryOperator<String> spellCheckerProcessing = 
 (String text) -> text.replaceAll("abc", "bcd"); 
Function<String, String> pipeline = 
 headerProcessing.andThen(spellCheckerProcessing); 
String result = pipeline.apply("Aren't abc really sexy?!!");

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值