zoukankan      html  css  js  c++  java
  • 简单工厂模式&策略模式简介与区别

    前言:两种模式的相似点与不同点

    不得不说,这两种模式真的很像。

    相似点:都用到了面向对象的继承、多态、抽象,都拥有相似的结构。

    不同点:工厂模式仅提供具体的实例对象,怎么使用这个对象是client的自由,策略模式client可以通过策略类来决定使用哪个实例的哪个方法。

    一、两种模式的公共相同部分

    下面,我们假设有一台红白机,里面有一些游戏,每个游戏拥有play(玩)和uninstall(卸载)两个方法。

    按照工厂和策略模式,我们抽象出来一个Game接口:

    
    public interface Game {
    
        void play();
    
        void uninstall();
    
    }
    

    然后,我们假设游戏机里有魂斗罗、马戏团、默认的俄罗斯方块三款游戏,每个游戏有不同的玩法和卸载算法:

    
    // 魂斗罗,实现Game
    public class Hundouluo implements Game {
        @Override
        public void play() {
            System.out.println("游戏:魂斗罗...playing");
        }
    
        @Override
        public void uninstall() {
            System.out.println("游戏:魂斗罗...卸载");
        }
    }
    
    // 马戏团,实现Game
    public class Maxituan implements Game {
    
        @Override
        public void play() {
            System.out.println("游戏:马戏团...playing");
        }
    
        @Override
        public void uninstall() {
            System.out.println("游戏:马戏团...卸载");
        }
    
    }
    
    // 默认的俄罗斯方块,实现Game
    public class Default implements Game {
    
        @Override
        public void play() {
            System.out.println("游戏:俄罗斯方块...playing");
        }
    
        @Override
        public void uninstall() {
            System.out.println("游戏:俄罗斯方块...卸载");
        }
    
    }
    

    ok,工厂模式和策略模式的相同部分就已经写好了,通过上面的代码,我们可以发现这两种模式都是需要把相同的部分抽象出来,通过多态来实例化不同的对象,调用其对应的实现。

    二、两种模式的不同部分的实现

    2.1:工厂模式

    工厂需要一个工厂类,用来返回具体的实例对象用,代码如下:

    
    public class GameFactory {
    
        public static Game getGame(String name) {
            switch (name) { //根据传来的游戏名(这里偷懒用了首字母),来实例化具体的对象
                case "hdl":
                    return new Hundouluo();
                case "mxt":
                    return new Maxituan();
                default:
                    return new Default();
            }
        }
    
    }
    

    2.2:策略模式

    策略模式需要策略类来封装具体的行为(方法),并且还可以指定使用哪个实例的哪个行为,代码如下:

    
    // 为了和工厂做充分的区分,这里定义了两个类型的context,分别维护一个行为算法(也就是方法函数,其次建立两个context是为了说明问题,实际使用时可能不需要这么多)
    
    // 用来维护play这个算法的实现
    public class PlayContext {
    
        private Game game;
    
        public PlayContext() {
            this.game = new Default();
        }
    
        public PlayContext(Game game) {
            this.game = game; // 这里根据传入的具体实例赋值
        }
    
        public void trigger() {
            this.game.play(); // 这里是对行为的封装,只提供play方法的触发
        }
    
    }
    
    // 用来维护uninstall这个算法的实现
    public class UninstallContext {
    
        private Game game;
    
        public UninstallContext() {
            this.game = new Default();
        }
    
        public UninstallContext(Game game) {
            this.game = game; // 这里根据传入的具体实例赋值
        }
    
        public void trigger() {
            this.game.uninstall(); // 这里是对行为的封装,只提供uninstall方法的触发
        }
    
    }
    

    测试代码:

    
    new PlayContext(new Hundouluo()).trigger();
    new UninstallContext(new Hundouluo()).trigger();
    new PlayContext(new Maxituan()).trigger();
    new UninstallContext(new Maxituan()).trigger();
    

    运行结果:

    
    游戏:魂斗罗...playing
    游戏:魂斗罗...卸载
    游戏:马戏团...playing
    游戏:马戏团...卸载
    

    通过上面的实验,和对比,会发现,工厂模式是简单的对实例的封装,而策略模式更在意的是对具体实例的具体行为(方法)的封装。

    还有一种情况就是利用工厂模式的思想,实现的策略模式,我们现在来改造下上面的PlayContext源码:

    
    public class PlayContext {
    
        private Game game;
    
        public PlayContext() {
            this.game = new Default();
        }
    
        public PlayContext(String name) {
            switch (name) { //根据传来的游戏名(这里偷懒用了首字母),来实例化具体的对象
                case "hdl":
                    this.game = new Hundouluo();
                    break;
                case "mxt":
                    this.game = new Maxituan();
                    break;
                default:
                    this.game = new Default();
            }
        }
    
        public void trigger() {
            this.game.play(); // 这里是对行为的封装,只提供play方法的触发
        }
    
    }
    

    测试类:

    
    new PlayContext("hdl").trigger();
    new UninstallContext(new Hundouluo()).trigger();
    new PlayContext("mxt").trigger();
    new UninstallContext(new Maxituan()).trigger();
    

    测试结果:

    
    游戏:魂斗罗...playing
    游戏:魂斗罗...卸载
    游戏:马戏团...playing
    游戏:马戏团...卸载
    

    三、总结

    策略模式是一种定义一系列算法的方法,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有算法,减少了各种算法类与使用算法类之间的耦合。

    工厂模式仅提供对应的实例,不对其方法做封装,减少了具体实现的实例与使用实例的业务方的耦合。

    (↑描述待改进)

  • 相关阅读:
    Vue系列:.sync 修饰符的作用及使用范例
    Vue系列:Websocket 使用配置
    Vue系列:Slot 插槽的使用范例
    Vue系列:滚动页面到指定位置实现
    Vue系列:为不同页面设置body背景颜色
    Element UI系列:Upload图片自定义上传
    Vue系列:wangEditor富文本编辑器简单例子
    Element UI系列:Select下拉框实现默认选择
    sublime text 3 15个常用插件介绍
    基于iis下 wcf接口发布
  • 原文地址:https://www.cnblogs.com/hama1993/p/10442519.html
Copyright © 2011-2022 走看看