23种经典设计模式之策略模式

前言

相信只要是学过java或者其他面向对象编程语言的伙伴们多少都听说过设计模式,比如可以说算是烂大街的mvc、单例模式都是其中之一。当然设计模式的家族很庞大,远远不止这些。那设计模式是用来干什么的呢?和我们平时开发的程序又有什么关系呢?我们应当如何去使用它呢?我会介绍23种经典的设计模式以供理解和学习。

继承

现在我列举一种日常开放过程中经常碰到的一个例子。小明是一个程序员,负责公司oa系统的开发。今天经理告诉他,需要给负责财务人员以及管理人员添加一个可以进行权限管理的功能。小明爽快的答应了。我们先看下小明原先的设计。


不同人员的行为都继承自person这个类,行为在person中都已实现,这样每个类复用时就不用重新再写一遍。小明依旧照着这个思路,在person这个父类中加入了manage这个方法。然后就变成了这样。

小明心想,直接在父类中写好实现,这样管理人员和财务人员通过继承就能直接获取这个方法了。写完代码,周末就happy去了。
然而愿望是美好的,现实是残酷的。周一,小明被叫进经理办公室,给狠狠批评了一顿。原因是开发组的成员也获得了管理公司oa系统的权限。
因为公司所有人员都是继承自person这个父类,一旦父类新增一个方法,他们都能自动获取。
小明说到:“要不直接把designer里的manage方法给覆盖掉?”经理怒到:“如果下次再添加一个人员类型呢?那是不是又得去覆盖一次?”
小明说:“那我可以把管理的方法变成一个接口,让需要管理方法的人员去继承它。”
经理说到:“还是不行的,如果有很多人员继承管理的接口,那岂不是每个类都要单独去写实现?”
听完经理这句话,小明这下陷入困境了。
这里我们先分析下这个问题,继承是一个非常强大的功能,但在这儿却并不能很好的解决问题。因为人员的行为在子类中不断变化,让所有子类继承父类所有的方法是不恰当的。另外将管理的行为封装成一个接口看起来不错但是接口意味没有实现代码,管理的方法无法被子类复用。所以同样解决不了问题。
幸好有一个设计的思想是用来解决此类情况的,

设计原则1:尽可能找出代码中经常变化的行为,并将其从代码中独立出来,不要和不变化的代码混在一起。

将类似管理这种不属于每个人员而且有可能发生变化的行为从人员类中分离出来,封装成一套独立的类。
不仅如此,我们还需要在产生一个人员实例时,可以动态的指定特定的管理行为给他它,并且可以在运行时做出改变。
为了实现这种效果,我们可以看下第二种设计原则

设计原则2:针对接口编程,而不是针对实现编程。

具体怎么做呢?这次人员类不会负责实现管理的接口,而是专门制造一组其他的行为类去实现管理的接口,这样的好处是:在人员的子类中将使用接口表示管理的行为,而接口的实现不会绑定到人员的子类中。
管理行为接口的关系如图所示,

如此以来管理的行为不仅仅可以被人员类使用,也可以被其他类复用,因为已经和人员类没有关系了。
那么我们现在开始修改之前的人员类型设计架构,首选在person类中加入manager实例

class Person{
    Manager manager;
    public void manage(){
        manager.manage();
    }
}
接下来看看具体子类的构造:
class Officer{
   public Officer(){
      manager = new FinaceManager();
   } 
}
像这样,我们可以在初始化officer实例时,指定其管理行为的实现类为finacemanager,在调用人员的管理manage方法时,实际上是委托给该对象的finacemanager对象去处理的。通过这种方式我们就实现了管理行为和人员类的分离。
但是如果想要更为弹性的设置人员的行为时,就不应该在构造器中初始化管理行为类。
在person类中新增一个方法
class Person{
    Manager manager;
    public void manage(){
        manager.manage();
    }
    public void setManager(Manager mg)    {
       this.manager = mg;
    }
}
然后我们整合起来看看测试类
class PersonTest{
    public static void main(String[] args)    {
       Person p = new Officer();
       p.manage();
       p.setManager(new personnelManager());
       p.manage();
    }
}
第一次调用manage方法时,会委托在构造器中设置的FinaceManager对象来完成,调用setManager方法后,第二次调用manage方法则换成了personnelManager对象。动态的绑定行为实现类就通过这种方式完成了。
这种将两个类结合起来使用,就是组合。和继承不同,人员的管理行为不是继承来的,而是和适当的行为对象“组合”来的。这种设计技巧也是一种设计原则:

设计原则3:多用组合,少用继承

通过以上例子,可以看到使用组合建立系统具有很大的弹性,不仅解决了继承造成的代码冗余,更能在运行时动态的改变行为。
以上这些设计原则综合起来就是一个经典的设计模式:策略模式。
用一句话来概括它:

策略模式:

将类中经常变化的行为分别疯子起来,使它们之间可以互相替换。这种模式让行为的改变独立于使用这些行为的客户类。

以上只是策略模式的一种适用场景,实际开发工作中可能有更多的场景可以去借鉴。

其实这些设计模式都是一种设计程序的经验,本着oo设计原则而产生的。

帮助我们更好的设计出拓展性更好的程序,提高我们的工作效率。

文章内容主要参考:《head first设计模式》


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值