精华内容
下载资源
问答
  • 策略模式+工厂模式+map 整理 项目中的switch case/if 转载:文章大佬写的文章 (如有侵权,请联系我,会立即删除) 接手新任务:接入第三家存证机构,看之前的代码使用了swith case判断使用哪家存证机构,每家存证...

    策略模式+工厂模式+map 整理 项目中的switch case/if
    转载:文章大佬写的文章 (如有侵权,请联系我,会立即删除)

    接手新任务:接入第三家存证机构,看之前的代码使用了swith case判断使用哪家存证机构,每家存证机构的实现逻辑不一样 代码的坏味道:多层swich case。多层swich case不好维护,是时候应该重构了,

    优化前的代码
    为了便于理解,举个没有业务逻辑的例子,基于这个例子上进行优化。 现在是12:47,举个饭后吃水果的例子哈哈哈(逃 假设我们可以选择的水果有香蕉、西瓜和苹果。吃香蕉的话我们得先剥皮,吃西瓜的话得先用水果刀切一下,如果是苹果的话就直接吃了。将这个场景转化为代码:

    	public class EatFruit {
        private static final String APPLE = "apple";
        private static final String BANANA = "banana";
        private static final String WATERMELON = "watermelon";
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            //选择的水果种类
            String fruitType = scanner.nextLine();
    
            switch (fruitType) {
                case APPLE:
                    eatApple();
                    break;
                case BANANA:
                    eatBanana();
                    break;
                case WATERMELON:
                    eatWatermelon();
                    break;
            }
        }
    
        private static void eatBanana() {
            System.out.println("吃香蕉了,需要先剥下皮");
        }
    
        private static void eatApple() {
            System.out.println("是苹果,可以直接吃");
        }
    
        private static void eatWatermelon() {
            System.out.println("吃西瓜了,但是还得弄把水果刀切一下先");
        }
    }
    

    这个例子代码量不是很大,但是实际项目中的场景肯定没有这么简单,多重swich case不好维护,并且万一又加了一样水果,还得继续加一层case…

    赶紧优化
    很容易想到策略模式(简单的理解就是多态),水果都有吃的一个动作,但是每种水果的吃法不一样
    使用策略模式进行优化

    Fruit.java
    
    public interface Fruit {
        void eat();
    }
    
    Apple.java
    
    public class Apple implements Fruit {
        @Override
        public void eat() {
            System.out.println("是苹果,可以直接吃");
        }
    }
    
    Banana.java
    
    public class Banana implements Fruit {
        @Override
        public void eat() {
            System.out.println("吃香蕉了,需要先剥下皮");
        }
    }
    
    Watermelon.java
    
    public class Watermelon implements Fruit {
        @Override
        public void eat() {
            System.out.println("吃西瓜了,但是还得弄把水果刀切一下先");
        }
    }
    

    但是发现即使用了策略模式也难逃类型判断 EatFruit.java

    	public class EatFruit {
        private static final String APPLE = "apple";
        private static final String BANANA = "banana";
        private static final String WATERMELON = "watermelon";
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            //选择的水果种类
            String fruitType = scanner.nextLine();
            Fruit fruit = null;
    
            switch (fruitType) {
                case APPLE:
                    fruit = new Apple();
                    break;
                case BANANA:
                    fruit = new Banana();
                    break;
                case WATERMELON:
                    fruit = new Watermelon();
                    break;
            }
    
            fruit.eat();
        }
    	}
    

    使用策略模式具有良好的扩展性,兵来将挡,再给我添加十种水果都不怕,水果种类太多会使水果的实现类暴增。现在来一种水果无需在原先的业务类(EatFruit)里修改很多的代码逻辑,只要实现接口并加个条件判断就好了。但是使用策略模式时,我们需要知道具体的实现类,具体的实现类需要对外暴露

    使用工厂模式
    将类型判断放到工厂类中 工厂模式:在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象,这里共同的接口就是Fruit。粗暴的讲,工厂模式就是把创建同一类型对象逻辑写在了一个方法里 FruitFactory .java

    	public class FruitFactory {
        public static Fruit getFruit(String fruitType) {
            if ("apple".equals(fruitType)) {
                return new Apple();
            }
    
            if ("banana".equals(fruitType)) {
                return new Banana();
            }
    
            return new Watermelon();
        }
    	}
    
    EatFruit .java
    
    public class EatFruit {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            //选择的水果种类
            String fruitType = scanner.nextLine();
            Fruit fruit = FruitFactory.getFruit(fruitType);
            fruit.eat();
        }
    }
    

    到现在为止EatFruit中的业务代码已经很清晰了。 使用工厂模式具有良好的封装性,这下妈妈再也不用关系创建类的过程,甚至连创建的实际类的都无需关心,实现了解耦,实际类的修改变化都不会影响上层业务
    但是工厂类中还是有很多if的,革命尚未成功,仍需要进行优化。

    map奥特曼来了

    FruitFactory.java
    
    public class FruitFactory {
        private static Map<String, Fruit> fruitMap = new HashMap<>();
    
        static {
            fruitMap.put("apple", new Apple());
            fruitMap.put("banana", new Banana());
            fruitMap.put("watermelon", new Watermelon());
        }
    
        public static Fruit getFruit(String fruitType) {
           return fruitMap.get(fruitType);
        }
    }
    

    通过使用map,fruitType与进行一一映射,和条件判断说byebye~,代码也很优雅 最终项目结构类图:

    有网友评论可以用反射替代map,如果传进来的是Class类型的值就可以用反射。用反射的好处是在添加多种水果,工厂类的代码都无需进行变动 通过反射替代map: FruitFactory2.java

    public class FruitFactory2 {
        public static <T extends Fruit> T getFruit(Class<T> fruitClass) throws IllegalAccessException, InstantiationException {
            return fruitClass.newInstance();
        }
    }
    
    展开全文
  • 在Spring中使用设计模式(策略模式+工厂模式)策略模式工厂模式测试 策略模式 设计模式,若使用得当,将会使我们的代码更简洁,并且更具扩展性。下面以支付为例 抽象一个支付接口 // 支付接口 public interface ...

    在Spring中使用设计模式(策略模式+工厂模式)

    策略模式

    设计模式,若使用得当,将会使我们的代码更简洁,并且更具扩展性。下面以支付为例

    • 依赖
    	<dependency>
    	      <groupId>org.springframework</groupId>
    	      <artifactId>spring-context</artifactId>
    	      <version>5.2.7.RELEASE</version>
    	 </dependency>
    
    • 抽象一个支付接口
    	// 支付接口
    	public interface IPay {
    	
    	    // 是否支持
    	    boolean support(Integer type);
    	
    	    //  支付
    	    void pay(WorkOrder workOrder);
    	}
    
    • 支付方式实现该接口
    1. 支付宝
    	@Component
    	public class AliPay implements IPay{
    	
    	   public boolean support(Integer type) {
    	        return type == PayType.UNIONPAY.getValue();
    	    }
    	
    	    public void pay(WorkOrder workOrder) {
    	        // 调用支付宝相关方法
    	        System.out.println("支付宝支付成功");
    	    }
    	}
    
    1. 微信支付
    	@Component
    	public class WechatPay implements IPay{
    	    public boolean support(Integer type) {
    	        return type == PayType.UNIONPAY.getValue();
    	    }
    	
    	    public void pay(WorkOrder workOrder) {
    	        //
    	        System.out.println("微信支付成功");
    	    }
    	}
    
    1. 银行卡支付
    	@Component
    	public class UnionPay implements IPay{
    	
    	    public boolean support(Integer type) {
    	        return type == PayType.UNIONPAY.getValue();
    	    }
    	
    	    public void pay(WorkOrder workOrder) {
    	        // 银行卡支付
    	        System.out.println("银行卡支付成功");
    	    }
    	}
    

    工厂模式

    	@Component
    	public class PayFactory {
    	   
    	    @Autowired
    	    private List<IPay> pays;
    	    
    	    public IPay getPay(Integer type){
            for (IPay pay : pays) {
                if(pay.support(type)){
                    return pay;
                }
            }
            throw new UnsupportedOperationException("Unsupported Pay");
        }
    
    	public class WorkOrder {
    	    private String id;
    	
    	    private String userId;
    	
    	    private Double price;
    	
    	    private int payType;
    		
    		// ... get、set省略
    	}
    
    	public enum PayType {
    	    ALIPAY(1),
    	    WECHATPAY(2),
    	    UNIONPAY(3);
    	
    	    private final int value;
    	
    	    PayType(int value){
    	        this.value = value;
    	    }
    	
    	    public int getValue() {
    	        return value;
    	    }
    	}
    
    @Service
    public class PayService {
    
        @Autowired
        private PayFactory factory;
    
        public void pay(WorkOrder workOrder){
            factory.getPay(workOrder.getPayType()).pay(workOrder);
        }
    }
    
    	@Configuration
    	@ComponentScan("com.qooence.code.service")
    	public class Config {
    	
    	}
    

    测试

    	public static void main(String[] args) {
    	        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
    	
    	        PayService payService = context.getBean(PayService.class);
    	
    	        WorkOrder workOrder = new WorkOrder();
    	        workOrder.setId("wo_2019_08_29_15_40_123");
    	        workOrder.setPrice(256.0);
    	        workOrder.setUserId("123");
    	        workOrder.setPayType(PayType.ALIPAY.getValue());
    	
    	        payService.pay(workOrder);
    	    }
    

    在这里插入图片描述

    展开全文
  • 或switch case代码的出现,可以使用策略模式+工厂模式进行优化。 在我的项目当中,报表繁多,所以尝试了这种方式进行优化报表的架构。代码很简单,如下: Factory工厂类 @Service public class ReportFactory { /*...

    为了防止大量的if...else...switch case代码的出现,可以使用策略模式+工厂模式进行优化。
    在我的项目当中,报表繁多,所以尝试了这种方式进行优化报表的架构。代码很简单,如下:

    Factory工厂类

    @Service
    public class ReportFactory {
    
        /**
         * 初始化的时候将所有的ReportService自动加载到Map中
         */
        @Autowired
        private final Map<String, ReportService> reportIns = new ConcurrentHashMap<>();
    
        public ReportService getReportIns(String code) {
            ReportService reportInstance = reportIns.get(code);
            if (reportInstance == null) {
                throw new RuntimeException("未定义reportInstance");
            }
    
            return reportInstance;
        }
    
    }
    

    接口

    public interface ReportService {
        String getResult();
    }
    

    实现类

    @Component(value = "A1")
    public class ReportServiceA1 implements ReportService {
    
        @Override
        public String getResult() {
            return "我是A1";
        }
    }
    
    @Component(value = "A2")
    public class ReportServiceA2 implements ReportService {
    
        @Override
        public String getResult() {
            return "我是A2";
        }
    }
    

    测试

    @SpringBootTest
    public class BlogServerApplicationTest {
    
        @Autowired
        ReportFactory reportFactory;
    
        @Test
        public void test2() {
            String result1 = reportFactory.getReportIns("A1").getResult();
            System.out.println("-----------------");
            System.out.println(result1);
            String result2 = reportFactory.getReportIns("A2").getResult();
            System.out.println("-----------------");
            System.out.println(result2);
        }
    }
    

    打印如下:

    -----------------
    我是A1
    -----------------
    我是A2
    

    总结

    在平时的工作当中,写一些业务代码是无可避免的,但是只要不局限于现状,往往可以发现不一样的乐趣。就像我在报表的业务中学习到了策略模式+工厂模式。

    个人博客网址: https://colablog.cn/

    如果我的文章帮助到您,可以关注我的微信公众号,第一时间分享文章给您
    微信公众号

    展开全文
  • 策略模式+工厂模式中,没有使用到模板模式,因为张三和李四的业务逻辑都是调用AAA方法,如果现在在增加一个方法,次方法只需要李四一人去实现BBB方法,此时张三的handel中就会报错,需要张三也去实现BBB方法,这时就出现...

    在策略模式+工厂模式中,没有使用到模板模式,因为张三和李四的业务逻辑都是调用AAA方法,如果现在在增加一个方法,次方法只需要李四一人去实现BBB方法,此时张三的handel中就会报错,需要张三也去实现BBB方法,这时就出现了模板模式,即将接口变为抽象类,实现自己的方法即可.

    优化前后:

    	@Test
    	String noDesign2() {
    		String name = "张三";
    
    		if (name.equals("张三")) {
    
    			// 业务逻辑A
    			return "张三完成任务AAA";
    
    		} else if (name.equals("李四")) {
    
    			// 业务逻辑B
    			return "李四完成任务BBB";
    
    		} 
    		return "end";
    	}
    
    	// 工厂 + 策略 + 模板设计模式
    	@Test
    	void design2() {
    		String name = "张三";
    
    		AbstractHandler strategy = Factory2.getInvokeStrategy(name);
    
    		strategy.AAA(name);
    
    		//strategy.BBB(name);
    	}

    AbstractHandler:

    import org.springframework.beans.factory.InitializingBean;
    
    /**
     * 模板方法设计模式
     */
    public abstract class AbstractHandler implements InitializingBean {
    
        public void AAA(String name) {
            throw new UnsupportedOperationException();
        }
    
        public String BBB(String name) {
            throw new UnsupportedOperationException();
        }
    }

    Factory2:

    import com.google.common.collect.Maps;
    import org.springframework.util.StringUtils;
    
    import java.util.Map;
    
    /**
     * 工厂设计模式
     */
    public class Factory2 {
        private static Map<String, AbstractHandler> strategyMap = Maps.newHashMap();
    
        public static AbstractHandler getInvokeStrategy(String str) {
            return strategyMap.get(str);
        }
    
        public static void register(String str, AbstractHandler handler) {
            if (StringUtils.isEmpty(str) || null == handler) {
                return;
            }
            strategyMap.put(str, handler);
        }
    }

    ZhangSanHandler2:

    import org.springframework.stereotype.Component;
    
    @Component
    public class ZhangSanHandler2 extends AbstractHandler {
    
        @Override
        public String AAA(String name) {
            // 业务逻辑B
            return "张三完成任务B";
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            Factory2.register("张三", this);
        }
    }
    

    LiSiHandler2:

    import org.springframework.stereotype.Component;
    
    @Component
    public class LiSiHandler2 extends AbstractHandler {
    
        @Override
        public String BBB(String name) {
            // 业务逻辑B
            return "李四完成任务B";
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            Factory2.register("李四", this);
        }
    }

     

    展开全文
  • 自定义支付注解=消除if:策略模式+工厂模式+单例模式 代码取景,知识来源于视频《云析学院【路飞老师】-一次学习终身受用-如何正确使用设计模式写出优雅的代码》 1、定义注解标签 PayChannel @Target(ElementType....
  • 一、现在有很多关于策略模式工厂模式和模板方法的介绍。但是基本都是main方法来展示的,不太清楚怎么移植到自己代码中。这里将其中if else当很多的时候,通过这三种模式与spring结合起来。 这个是当计算商品的价格...
  • } } 新建交易工厂,用于存储以后的交易类 public class TransFactory { private static Map transMap = Maps.newHashMap(); public static AbstractHandler getInvokHandler(String transNo) { return transMap....
  • 一、策略模式 策略模式定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换 1、策略模式主要角色 主要角色如下: 封装角色(Context):也叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、...
  • 策略模式工厂模式相信大家都比较熟悉,但是大家有没有在springboot中实现策略和工厂模式?  具体策略模式工厂模式的UML我就不给出来了,使用这个这两个模式主要是防止程序中出现大量的IF ELSE IF ELSE....。接...
  • 1、策略接口类PaperResultStrategy public interface PaperResultStrategy { AnswerReportDTO getResult(int projectId, int paperId); } 2、策略实现类PaperResultStrategyImpl2 @Component public class ...
  • * 策略设计模式 */ public interface Handler extends InitializingBean { public void AAA(String name); } 建立工厂(即去除if else),通过name,得到策略方法 import com.google.common.collect.M
  • 策略模式+工厂模式 去除if-else

    千次阅读 2019-11-03 12:48:07
    上述内容可看出,引入策略模式代码维护性和可读性有所增强,但是并未消除if-else 引入工厂模式 工厂类 public class UserPayServiceStrategyFactory{ private static Map, UserPayService> services = new ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 98,631
精华内容 39,452
关键字:

策略模式+工厂模式