简单工厂模式&策略模式-简介与区别

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

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

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

不同点:工厂模式仅提供具体的实例对象,怎么使用这个对象是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
游戏:马戏团...卸载

三、总结

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

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

(↑描述待改进)

posted @ 2019-02-27 11:24  是胖虎捏  阅读(957)  评论(0编辑  收藏  举报