策略模式 ——解决继承带来的苦恼

在最近的维护版本的开发中,常常碰到的一个问题:接手的项目中使用了OO的观念,但是大量使用继承,形成对子类的行为约束的过紧,子类很难扩展,此时若是修改父类的话,又容易误伤子类(由于一些子类的行为修改,而另外一些又不须要修改)。被百般折磨后发现了策率模式,故在此记录下。ide

为了表示结构,使用了下面的类图,很简单。DuckA,DuckB,DuckC均继承自Duck,并在Duck中实现了Swim()Quack(),因此如今的全部的鸭子都会游泳,都会叫,由于鸭子长的能够不同,因此在子类中分别实现了Display()。spa

Duck

这个结构没什么问题,也很不错,可是有一天突出需求变动了,要求鸭子们的叫声并不相同,但其中DuckA和DuckB叫声是相同,而且duckD不会叫;此时最容易想到一个办法是重写鸭子们的Quack()方法,而且DuckA和DuckB的实现是同样的,同时在DuckD中Quack()方法作一个空实现。这样实现虽然简单,可是问题不少,首先,DuckA和DuckB中的Quack代码重复的。当A,B的叫声发生变动时,将改两份代码(若是鸭子数量巨大的话,重复代码将更多);其次,若是有一天鸭子的叫声再次发生变化,那么你又要修改这些Qucak()方法。最后DuckD实际上不会叫,再将Quack()方法放到父类中感受也并不合适。设计

此时,咱们可能想到第二个方案是,将变化剥离出来,即将Quack()做成接口,会叫的鸭子实现该接口。这样看似很合适,由于解决了DuckD不会叫的问题,并且更加符合OO的设计。可是这并不能解决代码重复的问题,即DuckA,DuckB中Quack()的实现是同样的。继承了接口,可是依然没法达到代码的复用。code

此时咱们该怎么办呢?blog

DuackA

这个入很不专业,仅做示意吧。咱们能够将Quack抽象成接口,而且在父类中定义一个IQuack变量,但这个变量在子类中进行赋值。这样父类即可以操做IQuack接口。同时咱们将不一样的叫声分别实现出来,即QuackA,QuackB,QuackC.这样也解决了代码复用的问题。这样之后即使DuckC也更换叫声时,咱们也能够快速进行更换。继承

简单写了些代码:接口

public interface IQuack
    {
        void MakeQuack();
    }
    public  class  QuackA :IQuack
    {
        public void MakeQuack()
        {
           //QuackA
        }
    }

 

public abstract class Duck
    {
        public IQuack MyQuack;
        protected void Swim()
        {
            
        }
        protected virtual void Display()
        {
            
        }
        public void Quack()
        {
            MyQuack.MakeQuack();
        }
    }

    class  DuckA :Duck
    {
        public DuckA()
        {
            MyQuack = new QuackA();
        }
        protected override void Display()
        {
            // DuckA
        }
    }
相关文章
相关标签/搜索