zoukankan      html  css  js  c++  java
  • 策略模式 ——解决继承带来的苦恼

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

    为了表示结构,使用了下面的类图,很简单。DuckA,DuckB,DuckC均继承自Duck,并在Duck中实现了Swim()Quack(),所以现在的所有的鸭子都会游泳,都会叫,因为鸭子长的可以不一样,所以在子类中分别实现了Display()。

    Duck

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

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

    此时我们该怎么办呢?

    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
            }
        }
  • 相关阅读:
    SQL Server 触发器
    T-SQL查询进阶-10分钟理解游标
    有关T-SQL的10个好习惯
    iOS 画虚线以及drawRect的使用总结:
    iOS一个for循环实现,几行 几列 的布局形式
    IOS 符合某类型的子视图批量从父视图中移除
    DESC 和 ASC
    把数组格式数据转换成字符串存入数据库
    Swift :?和 !
    Swift 类构造器的使用
  • 原文地址:https://www.cnblogs.com/RealAlex/p/3290295.html
Copyright © 2011-2022 走看看