在最近的维护版本的开发中,常常碰到的一个问题:接手的项目中使用了OO的观念,但是大量使用继承,形成对子类的行为约束的过紧,子类很难扩展,此时若是修改父类的话,又容易误伤子类(由于一些子类的行为修改,而另外一些又不须要修改)。被百般折磨后发现了策率模式,故在此记录下。ide
为了表示结构,使用了下面的类图,很简单。DuckA,DuckB,DuckC均继承自Duck,并在Duck中实现了Swim()Quack(),因此如今的全部的鸭子都会游泳,都会叫,由于鸭子长的能够不同,因此在子类中分别实现了Display()。spa
这个结构没什么问题,也很不错,可是有一天突出需求变动了,要求鸭子们的叫声并不相同,但其中DuckA和DuckB叫声是相同,而且duckD不会叫;此时最容易想到一个办法是重写鸭子们的Quack()方法,而且DuckA和DuckB的实现是同样的,同时在DuckD中Quack()方法作一个空实现。这样实现虽然简单,可是问题不少,首先,DuckA和DuckB中的Quack代码重复的。当A,B的叫声发生变动时,将改两份代码(若是鸭子数量巨大的话,重复代码将更多);其次,若是有一天鸭子的叫声再次发生变化,那么你又要修改这些Qucak()方法。最后DuckD实际上不会叫,再将Quack()方法放到父类中感受也并不合适。设计
此时,咱们可能想到第二个方案是,将变化剥离出来,即将Quack()做成接口,会叫的鸭子实现该接口。这样看似很合适,由于解决了DuckD不会叫的问题,并且更加符合OO的设计。可是这并不能解决代码重复的问题,即DuckA,DuckB中Quack()的实现是同样的。继承了接口,可是依然没法达到代码的复用。code
此时咱们该怎么办呢?blog
这个入很不专业,仅做示意吧。咱们能够将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 } }