文学网站建设,wordpress的PC端和移动端,网页设计培训图片,wordpress是啥东西写在文章开头
本文将演示基于函数式编程的理念#xff0c;优化设计模式中繁琐的模板化编码开发#xff0c;以保证用尽可能少的代码做尽可能多的事#xff0c;希望对你有帮助。 Hi#xff0c;我是 sharkChili #xff0c;是个不断在硬核技术上作死的 java coder #xff…写在文章开头
本文将演示基于函数式编程的理念优化设计模式中繁琐的模板化编码开发以保证用尽可能少的代码做尽可能多的事希望对你有帮助。 Hi我是 sharkChili 是个不断在硬核技术上作死的 java coder 是 CSDN的博客专家 也是开源项目 Java Guide 的维护者之一熟悉 Java 也会一点 Go 偶尔也会在 C源码 边缘徘徊。写过很多有意思的技术博客也还在研究并输出技术的路上希望我的文章对你有帮助非常欢迎你关注我的公众号 写代码的SharkChili 。
因为近期收到很多读者的私信所以也专门创建了一个交流群感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加点击备注 “加群” 即可和笔者和笔者的朋友们进行深入交流。 详解lambda重构设计模式思路
策略模式
不同的业务对于字符串有着不同的匹配规则例如:长度是否大于10、是否全是大小、是否是电话号码等为了保证规则的复用我们通常会采用策略模式封装这些规则 对应的我们给出策略封装的接口定义
/*** 定义策略模式的接口*/
public interface ValidationStrategy {/*** 校验该字符串是否符合要求若符合则返回true* param str* return*/boolean execute(String str);
}
后续让我们的规则校验器将这个抽象的校验规则接口聚合进来如此我们就可以按照需求传入对应的校验规则策略strategy
public class Validator {//将校验规则聚合进来private ValidationStrategy strategy;public Validator() {}public Validator(ValidationStrategy strategy) {this.strategy strategy;}//基于聚合的strategy校验字符串strpublic boolean validate(String str) {return strategy.execute(str);}
}以下便是判断字符串是否全小写的校验规则实现
/*** 判断是否全为小写*/
public class IsAllLowerCase implements ValidationStrategy {Overridepublic boolean execute(String str) {return str.matches([a-z]);}
}完成后我们就可以将IsAllLowerCase实例化并传入校验器Validator 中进行使用了
//校验是否全是小写
Validator validator new Validator(new IsAllLowerCase());System.out.println(validator.validate(abc));//true可以看到我们的校验规则基本上一行就可以搞定为了这仅有的一行逻辑实现而编写大量的前置模板实在繁琐对此我们不妨基于之前所介绍的函数式编程的思路分析以下我们的ValidationStrategy本质上就只有一个抽象接口所以它完全可以被认定为一个函数式接口所以我们不妨将FunctionalInterface这个注解加上
FunctionalInterface
public interface ValidationStrategy {/*** 校验该字符串是否符合要求若符合则返回true* param str* return*/boolean execute(String str);
}
参考其抽象方法我们可以看到入参为String返回值为boolean由此推出函数描述符为(String)-boolean我们以上文全小写规则为例按照这个函数描述符的规则我们的表达式就是(s)-s.matches([a-z])是不是简化了许多呢 对应的我们给出简化后的代码 //校验是否全是小写Validator validator new Validator((s)-s.matches([a-z]));System.out.println(validator.validate(abc));模板方法
模板方法的理念是对于固化模板自实现然后将个性化业务下沉到不同业务场景自行开发我们以银行找到会员为例其大体步骤为
查询会员信息(固定)。招待会员。(不同银行流程不同)。 基于这个需求我们得出这样一个抽象类
public abstract class Banking {public void processCustomer(int id) {//查询会员信息String customer getCustomerWithId(id);//招待会员makeCustomerHappy(customer);}private String getCustomerWithId(int id) {return user-id;}//不同银行有不同的实现protected abstract void makeCustomerHappy(String customer);
}对应的我们给出BankingA 的招待逻辑:
public class BankingA extends Banking {Overrideprotected void makeCustomerHappy(String customer) {System.out.println(请customer吃饭并为其办理业务);}
}对应我们给出使用代码和输出结果
Banking bankingA new BankingA();bankingA.processCustomer(1);//输出请user-1吃饭并为其办理业务还是一样的问题为了仅仅一段简单的输出去适配模板方法从而编写出一段繁琐的代码很明显是需求简化的。
分析抽象方法makeCustomerHappy的定义要求传入String返回void由此我们按照函数式编程的套路得出可能要用到的函数式接口的函数描述符为:(String)-Void于是我们得到了一个JDK8自带的接口Consumer它的函数签名为(T)-Void注意这个T是泛型所以我们完全可以将String类等价代入 这里我们也给出Consumer的源码读者可自行查阅
FunctionalInterface
public interface ConsumerT {//......void accept(T t);}对此我们将抽象类Banking 加以改造将抽象方法makeCustomerHappy改为Consumer接口
public class Banking {public void processCustomer(int id, ConsumerString makeCustomerHappy) {//查询会员信息String customer getCustomerWithId(id);//招待会员makeCustomerHappy.accept(customer);}private String getCustomerWithId(int id) {return user-id;}}于是我们的代码就简化成了下面这样 Banking bankingA new BankingA();bankingA.processCustomer(1, (s) - System.out.println(请 s 吃饭并为其办理业务));观察者模式
观察者模式算是最经典也最好理解的设计模式观察者只需将自己注册到感兴趣的主题上一旦有主题更新就会及时通知观察者处理该消息 基于这种设计模式的理念我们给出观察者的接口的定义:
/*** 观察者*/
public interface Observer {//主题有更新调用该方法通知观察者void inform(String msg);
}然后就是主题接口的定义
public interface Subject {//注册观察者void registerObserver(Observer observer);//通知消息给所有观察者void notifyObserver();
}对此我们给出一个观察者的实现
public class Observer1 implements Observer {Overridepublic void inform(String msg) {System.out.println(观察者1收到通知内容为 msg);}
}最后就是主题类的实现我们将观察者聚合如果观察者对SubJect1 感兴趣则通过registerObserver完成注册一旦主题要发布新消息就可以通过notifyObserver及时通知每一个订阅者:
public class SubJect1 implements Subject {private String msg;public SubJect1(String msg) {this.msg msg;}private ListObserver observerList new ArrayList();//将观察者添加到订阅者列表Overridepublic void registerObserver(Observer observer) {observerList.add(observer);}//有新消息通知订阅列表的所有用户Overridepublic void notifyObserver() {observerList.forEach(o - o.inform(msg));}
测试代码和对应输出结果如下所示
public static void main(String[] args) {SubJect1 subJect1 new SubJect1(请大家学习《基于lambda简化设计模式》);//注册订阅者subJect1.registerObserver(new Observer1());//主题发起通知subJect1.notifyObserver();//观察者1收到通知内容为请大家学习《基于lambda简化设计模式》}每一个观察都是一行代码为了这一行创建一个类显得有些繁琐仔细查看registerObserver方法的定义我们可以得出该方法的签名为Observer-Void由此我们可以推导出对应的lambda表达式 由此我们可以直接将上述Observer1的代码简化为lambda表达式对应代码示例如下 subJect1.registerObserver(s - System.out.println(观察者1收到消息 s));责任链模式
责任链在Spring或者Netty这种大型框架中非常常见它通过链式关系顺序的调用处理器处理当前业务数据举个例子我们希望字符串被对象1处理完成之后要转交给对象2处理并且我们后续可能还会交给更多的对象处理通过对需求的梳理和抽象这个功能可以通过责任链模式来实现。 首先声明责任链上每一个处理器的抽象类考虑到通用性笔者将这个类的入参设置为泛型并且公共方法handle的步骤为:
调用自己的handWork处理输入数据handWork交给实现类自行编写。若successor不为空则将处理结果交给下一个处理器处理由此构成一条处理链。
public abstract class ProcessingObjectT {/*** 下一个处理器*/private ProcessingObjectT successor;public ProcessingObjectT getSuccessor() {return successor;}public void setSuccessor(ProcessingObjectT successor) {this.successor successor;}public T handle(T input) {//先自己处理完如果有后继责任链则交给后面的责任链处理递归下去T t handWork(input);if (successor ! null) {return successor.handWork(t);}return t;}/*** 自己的处理逻辑** param intput* return*/abstract T handWork(T intput);
}对应的我们基于这个抽象类实现两个字符处理器ProcessingStr1会将收到的中文逗号换位英文逗号
public class ProcessingStr1 extends ProcessingObjectString {OverrideString handWork(String intput) {return intput.replace(, ,);}
}而ProcessingStr2 会将中文句号替换为英文句号
public class ProcessingStr2 extends ProcessingObjectString {OverrideString handWork(String intput) {return intput.replace(。, .);}
}测试代码和输出结果如下
public static void main(String[] args) {ProcessingObjectString p1 new ProcessingStr1();ProcessingObjectString p2 new ProcessingStr2();p1.setSuccessor(p2);System.out.println(p1.handle(helloworld。));}可以看到所有的中文符号都被替换成英文符号了:
hello,world.话不多说不难看出上文这种传入String返回String的方法我们完全可以使用UnaryOperator函数式接口它的函数式签名为(T)-T很明显将我们的String类代入是成立的 FunctionalInterface
public interface UnaryOperatorT extends FunctionT, T {static T UnaryOperatorT identity() {return t - t;}
}于是我们的责任链的处理器就被简化为下面这样
//逗号替换UnaryOperatorString p1 i - i.replace(, ,);//句号替换
UnaryOperatorString p2 i - i.replace(。, .);为了让两个处理器构成逻辑链我们直接使用函数复合方法andThen确保p1执行玩调用p2:
FunctionString, String function p1.andThen(p2);
System.out.println(function.apply(helloworld。));//hello,world.小结
对于逻辑比较简单且需要适配设计模式的功能可以尝试找到合适的函数式接口按照它的签名实现功能避免没必要的模板配置工作。
以上便是笔者关于Java8中函数式设计模式的案例实践全部内容希望对你有帮助。
我是 sharkchili CSDN Java 领域博客专家开源项目—JavaGuide contributor我想写一些有意思的东西希望对你有帮助如果你想实时收到我写的硬核的文章也欢迎你关注我的公众号 写代码的SharkChili 。 因为近期收到很多读者的私信所以也专门创建了一个交流群感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加点击备注 “加群” 即可和笔者和笔者的朋友们进行深入交流。 参考
Java 8 in Action:https://book.douban.com/subject/25912747/