业务逻辑一致:
我们在开发过程中经常会遇到很多冗余代码,今天学习了一下如何消除那些冗余代码,提高代码可读性,我来分享一下:
public class IfAndElesDemo {
public static void main(String[] args) {
String nickName = "basketball";
if ("basketball".equals(nickName)) {
//这里就是if else里面的业务逻辑
//将if里面的每个分支看成一个策略
System.out.println("我是篮球");
} else if ("football".equals(nickName)) {
//...
System.out.println("我是足球");
} else if ("baseball".equals(nickName)) {
//...
System.out.println("我是棒球");
}
}
我们看到代码有很多冗余,我们来一步一步优化他,先创建一个策略模式的接口类,里面定义方法实际就是抽出来的:
import org.springframework.beans.factory.InitializingBean;
/**
* 我们定义一个策略的接口类
*/
public interface TotalHandler extends InitializingBean {
void play(String nickName);
}
然后实现对应的策略类,把我们的业务逻辑放进我们的play方法里面,篮球:
/**
* 篮球的策略类
*/
@Component
public class BasketballHandler implements TotalHandler {
@Override
public void play(String nickName) {
//业务逻辑
System.out.println("我是篮球");
}
@Override
public void afterPropertiesSet() throws Exception {
}
}
足球:
/**
* 足球的策略类
*/
@Component
public class FootballHandler implements TotalHandler{
@Override
public void play(String nickName) {
//业务逻辑
System.out.println("我是足球");
}
@Override
public void afterPropertiesSet() throws Exception {
}
}
棒球:
/**
* 棒球的策略类
*/
@Component
public class BaseballHandler implements TotalHandler{
@Override
public void play(String nickName) {
//业务逻辑
System.out.println("我是棒球");
}
@Override
public void afterPropertiesSet() throws Exception {
}
}
这时候完成第一步了,优化后:
public class IfAndElesDemo {
public static void main(String[] args) {
String nickName="basketball";
if ("basketball".equals(nickName)){
//这里就是if else里面的业务逻辑
//将if里面的每个分支看成一个策略
//优化成以下代码
new BasketballHandler().play("basketball");
}else if ("football".equals(nickName)){
//...
//优化成以下代码
new BasketballHandler().play("football");
}else if ("baseball".equals(nickName)){
//...
//优化成以下代码
new BasketballHandler().play("baseball");
}
}
但是我们看到代码的骨架还在,就是If,else,我们继续,这里需要用到工厂模式,先抽出一个工厂类,工厂类里面有一个map,key是string,value就是我们的策略类
import java.util.HashMap;
import java.util.Map;
/**
* 工厂设计模式
*/
public class TotalFactory {
private static Map<String, TotalHandler> handlerMap=new HashMap<>();
/**
* 根据不同的名字拿到不同的策略
* @param nickName
* @return
*/
public static TotalHandler getInstanceHandler(String nickName){return handlerMap.get(nickName);};
public static void register(String name,TotalHandler handler){
handlerMap.put(name,handler);
}
}
然后再给具体的策略类里面将策略注册进去:
TotalFactory.register("basketball",this);
优化后:
public class IfAndElesDemo {
public static void main(String[] args) {
String nickName = "basketball";
//工厂根据名字拿到不同的策略
TotalHandler instanceHandler = TotalFactory.getInstanceHandler(nickName);
//策略对象调用方法
instanceHandler.play(nickName);
}
}
业务逻辑不一致:
可以换一种,这时候就需要加上模板方法了:
先定义一个抽象的模板方法类
import org.springframework.beans.factory.InitializingBean;
/**
* 定义一个抽象的模板方法类 抛出UnsupportedOperationException是因为两个方法可以选其中一个实现而不是都去实现
* 具体类去实现需要的具体方法就行
*/
public abstract class AbstractTotalHandler implements InitializingBean {
/**
* @param nickName
*/
public void play(String nickName){
throw new UnsupportedOperationException();
}
/**
* @param nickName
*/
public void eat(String nickName){
throw new UnsupportedOperationException();
}
}
再多写一个handler,注册抽象出来的策略
import java.util.HashMap;
import java.util.Map;
public class AbstractTotalFactory {
private static Map<String, AbstractTotalHandler> handlerMap=new HashMap<>();
/**
* 将TotalHandler换成AbstractTotalHandler
* 根据不同的名字拿到不同的策略
* @param nickName
* @return
*/
public static AbstractTotalHandler getInstanceHandler(String nickName){return handlerMap.get(nickName);};
public static void register(String name,AbstractTotalHandler handler){
handlerMap.put(name,handler);
}
}
给大家举个例,我这定义了一个草莓类:
/**
* 草莓的策略类,这里就是继承我们的抽象策略类
*/
@Component
public class StrawberryHandler extends AbstractTotalHandler{
@Override
public void eat(String nickName) {
System.out.println("我在吃草莓");
}
@Override
public void afterPropertiesSet() throws Exception {
AbstractTotalFactory.register("strawberry",this);
}
}
我们只需要从抽象工厂类里面拿到抽象的策略对象就可以了,很方便:
public class IfAndElesDemo {
public static void main(String[] args) {
String nickName="strawberry";
//工厂根据名字拿到不同的抽象策略
AbstractTotalHandler instanceHandler = AbstractTotalFactory.getInstanceHandler(nickName);
//抽象的策略对象调用不同的方法
instanceHandler.play(nickName);
instanceHandler.eat(nickName);
}
}