策略模式对比工厂模式

从策略一词来看,策略模式是种倾向于行为的模式.有点类似打仗时的做战方案,一般司令员在做战前都会根据实际情况做出几套不同的方案,如果当时情况有变,就会根据相应的条件来判定用哪一套方案来替换原定方案。但无论如何替换,替换多少次,仗还是要打的。

策略模式的UML图

策略模式与工厂模式从uml图上来说,基本一致。只是强调的封装不同。我们以工厂模式和策略模式的比较来讲解策略模式。
工厂模式分为简单工厂、工厂方法模式、抽象工厂模式,我们来举例说明。
工厂模式我们可以做如下理解:假设有Audi的公司生产汽车,它掌握一项核心的技术就是生产汽车,另一方面,它生产的汽车是有不同型号的,并且在不同的生产线上进行组装。当客户通过销售部门进行预定后,Audi公司将在指定的生产线上为客户生产出它所需要的汽车。

//工厂模式
//抽象产品  
abstract class AudiCar{  
    private String name;  
      
    public abstract void makeCar();  
      
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
}  
//具体产品  
class AudiA6 extends AudiCar{  
    public void makeCar(){  
        System.out.println(this.getName()+"----go-----------------------");  
    }  
}  
class AudiA4 extends AudiCar{  
    public void makeCar(){  
        System.out.println(this.getName()+"----go-----------------------");  
    }  
}  
  
//简单工厂---销售部门----服务端  
class CarFactroy{  
    public static AudiCar createCar(String car){  
        AudiCar c = null;  
        if("A6".equalsIgnoreCase(car))  
            c = new AudiA6();  
        else if("A4".equalsIgnoreCase(car))  
            c = new AudiA4();  
        return c;  
    }  
}  
  
//客户----客户端(这个客户是外行,什么都不懂,只要随便描述下车,销售部门才能知道他要那款车,所以销售部门比较牛)  
public class SimplyFactoryAndStrategy {  
  
    public static void main(String[] args) throws IOException {  
          
        System.out.print("请输入您要坐的车:(A6、A4)");  
        String carName = new BufferedReader(new InputStreamReader(System.in)).readLine();  
          
        //客户说我要什么什么样子的车子,销售人员才知道他要什么样子的车子  
        AudiCar car = CarFactroy.createCar(carName);  
        car.setName(carName);  
        car.makeCar();    
    }  
}  

策略(Strategy)模式在结构上与工厂模式类似,唯一的区别是工厂模式实例化一个产品的操作是在服务端来做的,换句话说客户端传达给服务端的只是某种标识,服务端根据该标识实例化一个对象。而策略模式的客户端传达给服务端的是一个实例,服务端只是将该实例拿过去在服务端的环境里执行该实例的方法。

//策略模式
//抽象产品  
abstract class AudiCar{  
    private String name;  
      
    public abstract void makeCar();  
      
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
}  
//具体产品  
class AudiA6 extends AudiCar{  
    public void makeCar(){  
        System.out.println(this.getName()+"----go-----------------------");  
    }  
}  
class AudiA4 extends AudiCar{  
    public void makeCar(){  
        System.out.println(this.getName()+"----go-----------------------");  
    }  
}  
  
//销售部门----服务端  
class CarContext {  
    AudiCar audiCar = null;  
  
    public CarContext(AudiCar audiCar) {  
        this.audiCar = audiCar;  
    }  
      
    public void orderCar(){  
        this.audiCar.makeCar();  
    }  
}  
  
//客户----客户端(这个客户是内行,什么都懂,他说我要A6,销售部门立刻给他a6,所以销售部门不用很懂)  
public class SimplyFactoryAndStrategy2 {  
  
    public static void main(String[] args) throws IOException {  
          
        //客户说我要什么什么样子的车子,销售人员才知道他要什么样子的车子  
        AudiCar car = new AudiA6();  
        car.setName("a6");  
          
        CarContext context = new CarContext(car);  
        context.orderCar();  
    }  
}  

工厂模式和策略模式的区别在于实例化一个对象的位置不同,对工厂模式而言,实例化对象是放在服务端的,即放在了工厂类里面;
而策略模式实例化对象的操作在客户端,服务端的“销售部门”只负责传递该对象,并在服务端的环境里执行特定的操作。
工厂模式要求服务端的销售部门足够灵敏,而策略模式由于对策略进行了封装,所以他的销售部门比较傻,需要客户提供足够能区分使用哪种策略的参数,而这最好的就是该策略的实例了。
策略模式的优缺点

策略模式的主要优点有:

1.策略类之间可以自由切换,由于策略类实现自同一个抽象,所以他们之间可以自由切换。
2.易于扩展,增加一个新的策略对策略模式来说非常容易,基本上可以在不改变原有代码的基础上进行扩展。
3.避免使用多重条件,如果不使用策略模式,对于所有的算法,必须使用条件语句进行连接,通过条件判断来决定使用哪一种算法,在上一篇文章中我们已经提到,使用多重条件判断是非常不容易维护的。

策略模式的缺点主要有两个:

1.维护各个策略类会给开发带来额外开销,可能大家在这方面都有经验:一般来说,策略类的数量超过5个,就比较令人头疼了。
2.必须对 客户端(调用者)暴露所有的策略类,因为使用哪种策略是由客户端来决定的,因此,客户端应该知道有什么策略,并且了解各种策略之间的区别,否则,后果很严 重。例如,有一个排序算法的策略模式,提供了快速排序、冒泡排序、选择排序这三种算法,客户端在使用这些算法之前,是不是先要明白这三种算法的适用情况? 再比如,客户端要使用一个容器,有链表实现的,也有数组实现的,客户端是不是也要明白链表和数组有什么区别?就这一点来说是有悖于迪米特法则的。

适用场景

做面向对象设计的,对策略模式一定很熟悉,因为它实质上就是面向对象中的继承和多态,在看完策略模式的通用代码后,我想,即使之前从来没有听说过策略模式,在开发过程中也一定使用过它吧?

至少在在以下两种情况下,大家可以考虑使用策略模式,

几个类的主要逻辑相同,只在部分逻辑的算法和行为上稍有区别的情况。
有几种相似的行为,或者说算法,客户端需要动态地决定使用哪一种,那么可以使用策略模式,将这些算法封装起来供客户端调用。


策略模式是一种简单常用的模式,我们在进行开发的时候,会经常有意无意地使用它,一般来说,策略模式不会单独使用,跟模版方法模式、工厂模式等混合使用的情况比较多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隔窗听雨眠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值