文章预览
优化 if else
参考:
《阿里巴巴java编码规范》、《设计模式》(清华大学出版)、https://blog.csdn.net/mifffy_java/article/details/95201289
1、 阿里编程归约
对于控制语句,阿里归约上推荐了一种思路。【推荐】在表达异常的分支时,尽量少用
if else
方式,这种方式可以改写成:
if(condition){
...
return obj;
}
说明:如果不得不使用
if()...else if()...else...
方式表达逻辑,
【强制】避免后序代码维护困难,请勿超过3层。
正例:超过3层的
if else
逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,其中卫语句示例如下:
public void today(){
if(isBusy()){
System.out.println("change time.");
return;
}
if(isFree()){
System.out.println("go to travel.");
return;
}
Sysout.out.println("stay at home. learning java.");
return;
}
说明:卫语句就是把复杂的条件表达式拆分成多个条件表达式,条件为真时,立刻从方法体中返回给调用方。卫语句的好处是条件表达式之间相互独立,不会互扰。
2、 switch 语句
多个
if else
的写法:
char status = 'B';
if('A' == status){
functionA();
} else if('B' == status){
functionB();
} else if('C' == status){
functionC();
} else {
...
}
使用
switch case
语句:
switch(status){
case 'A':
functionA();
break;
case 'B':
functionB();
break;
case 'C':
functionC();
break;
default:
break;
}
3、数组
来自google解释,这是一种编程模式,叫做表驱动法,本质是从表里查询信息来代替逻辑语句。
【案例1】
定义一个接口数组,这是一个函数式接口,其中的方法是单参数无返回值的。
可以使用不同的样式打印传入的参数:
Consumer[] consumers = {
System.out::println,
arg -> System.out.println("[" + arg + "]"),
arg -> System.out.println("(" + arg + ")"),
arg -> System.out.println("{" + arg + "}")
};
for (Consumer consumer : consumers) {
consumer.accept("这句话会打印出来");
}
【案例2】
if else
的写法:
定义一个方法,获取星期数。
private static String getWeekDay(int weekStat) {
if (0 == weekStat) {
return "星期天";
}
if (1 == weekStat) {
return "星期一";
}
if (2 == weekStat){
return "星期二";
}
if (3 == weekStat){
return "星期三";
}
if (4 == weekStat){
return "星期四";
}
if (5 == weekStat){
return "星期五";
}
if (6 == weekStat){
return "星期六";
}
return null;
}
int weekStat = 1;
String weekDay = getWeekDay(1);
System.out.println(weekDay);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
使用数组优化:
String[] week = {
"星期天",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六"
};
int weekStat = 1;
String weekDay = week[weekStat];
System.out.println(weekDay)
4、Optional解决判空的if else
环境:基于 jdk8 (高版本还有更厉害、方便的方法,这里不做讨论)
【案例1】
String pictureName = "真香.png";
Optional.of(pictureName).ifPresent(System.out::println);
【案例2】
class User {
String name;
String password;
}
public class Demo {
public static void main(String[] args) {
User user = new User();
user.name = "小冯";
Optional.of(user)
.filter(u -> "123456".equals(u.password))
.ifPresent(System.out::println);
Optional.of(user).map(u -> u.name).ifPresent(System.out::println);
}
}
5、策略设计模式
概念:来自《设计模式》(清华大学出版社)
策略设计模式用于算法的自由切换和扩展。策略模式对应于解决某一问题的一个算法族,允许用户从该算法中任选一个算法解决某一问题,同时可以方便的更换算法或增加新的算法。
5.1 枚举实现
定义一个枚举类:
enum WeekDay {
Sunday("Sunday"){
@Override
void weekRun() {
System.out.println(weekName + ":和朋友出去玩!");
}
},
Monday("Monday"){
@Override
void weekRun() {
System.out.println(weekName + ":在学校学习英语");
}
},
Tuesday("Tuesday"){
@Override
void weekRun() {
System.out.println(weekName + ":在学校学习java");
}
},
Wednesday("Wednesday"){
@Override
void weekRun() {
System.out.println(weekName + ":在学校学习语文");
}
},
Thursday("Thursday"){
@Override
void weekRun() {
System.out.println(weekName + ":在学校学习历史");
}
},
Friday("Friday"){
@Override
void weekRun() {
System.out.println(weekName + "在学校玩");
}
},
Saturday("Saturday"){
@Override
void weekRun() {
System.out.println(weekName + "和朋友在家看电影");
}
};
public String weekName;
abstract void weekRun();
WeekDay(String weekName){
this.weekName = weekName;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
使用该枚举类:
public class Demo {
public static void main(String[] args) {
WeekDay.valueOf("Sunday").weekRun();
WeekDay.Monday.weekRun();
}
}
5.2 多态实现
【案例1】
此处参见我的数组的那个案例,使用函数式接口的数组,实现了多态。
【案例2】
当不使用 Lambda 优化写法时,我重新设计了一个场景,抽象一个跑的行为抽象:
@FunctionalInterface
interface RunStrategy {
void run();
}
针对该行为抽象,有几种实现:
class PeopleRunStrategy implements RunStrategy {
@Override
public void run() {
System.out.println("人用腿跑");
}
}
class CarRunStrategy implements RunStrategy {
@Override
public void run() {
System.out.println("汽车用轮子跑");
}
}
class FishRunStrategy implements RunStrategy {
@Override
public void run() {
System.out.println("鱼在水里游");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
调用:
RunStrategy peopleRun = new PeopleRunStrategy();
peopleRun.run();
5.3 map 优化
针对 5.2 多态实现的策略设计模式,使用映射来调用:
Map<String, RunStrategy> runStrategyMap = new HashMap<>(16);
runStrategyMap.put("people", new PeopleRunStrategy());
runStrategyMap.put("car", new CarRunStrategy());
runStrategyMap.put("fish", new FishRunStrategy());
RunStrategy runStrategy1 = runStrategyMap.getOrDefault("car", new PeopleRunStrategy());
RunStrategy runStrategy2 = runStrategyMap.getOrDefault("bird", new PeopleRunStrategy());
runStrategy1.run();
runStrategy2.run();
5.4 工厂设计模式优化
接口与实现类:
与 5.2 中的【案例2】一致。
工厂类:
class RunStrategyFactory {
private RunStrategyFactory(){}
private static final Map<String, RunStrategy> RUN_STRATEGY_MAP = new ConcurrentHashMap<>(16);
static {
RUN_STRATEGY_MAP.put("peopleRunStrategy", new PeopleRunStrategy());
RUN_STRATEGY_MAP.put("fishRunStrategy", new FishRunStrategy());
}
public static RunStrategy getInstance(String strategy){
return RUN_STRATEGY_MAP.getOrDefault(strategy, new PeopleRunStrategy());
}
public static Map<String, RunStrategy> getRunStrategyMap(){
return RUN_STRATEGY_MAP;
}
public static void registerStrategy(RunStrategy runStrategy){
String strategy = runStrategy.getClass().getSimpleName();
strategy = strategy.substring(0, 1).toLowerCase() + strategy.substring(1);
RUN_STRATEGY_MAP.put(strategy, runStrategy);
}
public static void registerStrategy(String strategy, RunStrategy runStrategy){
RUN_STRATEGY_MAP.put(strategy, runStrategy);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
运行测试:
public static void main(String[] args) {
RunStrategyFactory.getInstance("fishRunStrategy").run();
RunStrategyFactory.registerStrategy(new CarRunStrategy());
RunStrategyFactory.registerStrategy("snakeRunStrategy",() -> System.out.println("蛇在地上爬"));
RunStrategyFactory.getRunStrategyMap().forEach((k, v) -> {
System.out.println("Strategy = " + k);
v.run();
});
}
运行结果:
鱼在水里游
Strategy = carRunStrategy
汽车用轮子跑
Strategy = peopleRunStrategy
人用腿跑
Strategy = fishRunStrategy
鱼在水里游
Strategy = snakeRunStrategy
蛇在地上爬
6、 状态设计模式
概念:来自《设计模式》(清华大学出版社)
状态设计模式是一种较为复杂的设计模式,它用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态设计模式。
该模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
状态模式描述了对象状态的变化以及对象如何在每一种状态下表现出不同的状态。
【案例】
抽象状态行为接口:
@FunctionalInterface
interface State {
void handle();
}
具体的状态类:
class FreeState implements State {
@Override
public void handle() {
System.out.println("闲着就写代码!!");
}
}
class BusyState implements State {
@Override
public void handle() {
System.out.println("忙了还得写代码!!!");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
环境类:
class Context {
private State state;
public void setState(State state){
this.state = state;
state.handle();
}
public State getState(){
return state;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
客户端测试:
public class ContextClient {
public static void main(String[] args) {
Context context = new Context();
context.setState(new FreeState());
context.setState(new BusyState());
context.setState(() -> System.out.println("这是Lambda 状态啊!!!"));
}
}
测试结果:
闲着就写代码!!
忙了还得写代码!!!
这是Lambda 状态啊!!!
7、 职责链设计模式
概念:来自《设计模式》(清华大学出版社)
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
【案例】:模拟《LOL》游戏场景。假设,有个游戏角色叫【盖伦】,满血量有5200,纯防御装备。现在有对手阵营的角色【亚索】,【光辉】,【诺手】来抓他。盖伦有血量,当盖伦血量低于 2000时,【光辉】可以杀他;当盖伦血量低于4000时,【亚索】可以杀他;当盖伦血量低于5200时,【诺手】可以杀他。
能想到这个案例,我也是秀了(参考于英雄联盟游戏,哈哈)
友军抽象类:
abstract class BaseFriendly {
protected BaseFriendly friendly;
public void setFriendly(BaseFriendly friendly){
this.friendly = friendly;
}
abstract void handleEnemy(BaseEnemy enemy);
}
友军子类:
class YaSuo extends BaseFriendly {
@Override
void handleEnemy(BaseEnemy enemy) {
int hp = 4000;
if(enemy.getHp() <= hp){
System.out.println(enemy.getName() + "的血量小于4000, 亚索杀了他。");
} else {
setFriendly(new NuoShou());
System.out.println(enemy.getName() + "的血量是" + enemy.getHp() + ",亚索打不过,亚索叫来了诺手");
this.friendly.handleEnemy(enemy);
}
}
}
class GuangHui extends BaseFriendly {
@Override
void handleEnemy(BaseEnemy enemy) {
int hp = 2000;
if(enemy.getHp() <= hp){
System.out.println(enemy.getName() + "的血量小于2000, 光辉杀了他。");
} else {
setFriendly(new YaSuo());
System.out.println(enemy.getName() + "的血量是" + enemy.getHp() + ",光辉打不过,光辉叫来了亚索!");
this.friendly.handleEnemy(enemy);
}
}
}
class NuoShou extends BaseFriendly {
@Override
void handleEnemy(BaseEnemy enemy) {
System.out.println(enemy.getName() + "的血量是" + enemy.getHp() + ",诺手杀了他。");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
敌军抽象类:
abstract class BaseEnemy{
private int hp;
private String name;
public BaseEnemy (String name, int hp){
this.name = name;
this.hp = hp;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
敌军子类:
class GaiLun extends BaseEnemy {
public GaiLun(String name, int hp) {
super(name, hp);
}
}
客户端测试:
public class HandlerClient {
public static void main(String[] args) {
BaseEnemy gaiLun = new GaiLun("盖伦", 4700);
BaseFriendly guangHui = new GuangHui();
guangHui.handleEnemy(gaiLun);
System.out.println("------------------------");
gaiLun.setHp(1880);
guangHui.handleEnemy(gaiLun);
}
}
测试结果:
盖伦的血量是4700,光辉打不过,光辉叫来了亚索!
盖伦的血量是4700,亚索打不过,亚索叫来了诺手
盖伦的血量是4700,诺手杀了他。
------------------------
盖伦的血量小于2000, 光辉杀了他。
………………………………