Head First设计模式

  看了第一章的入门内容,我觉得真的很有意思,下面我就把书上那个对Duck类的学习总结一下,我们从问题的提出开始。问题一开始是这样的:设计一个Duck类,这个类时很多种类鸭子的超类,于是,我们不加思索的设计了下面的代码:

  

 public class Duck{
 void quack();//鸭子叫声
virtual void display();//鸭子的外观显示
 void swim();//鸭子都会游泳
}

public class MallardDuck:Duck{
void override display()
{
//显示为绿鸭子
}
}
public class ReadheadDuck:Duck{
void override display()
{
//显示为红鸭子
}
}

  这样设计看似非常的完美,但是软件人员心中唯一的真理是“change”。过了一段时间,我们需要给鸭子天上能够飞翔的功能,看似只需要在Duck类中加入void fly()这个函数就可以了,但是,这是现实并不想我们想的那样,出现了木头鸭子也会飞翔的情况,这时们会想,我们可以把fly做成为virtual类型的,在木头鸭子中把它覆盖掉就可以了,不让他做任何的事情就可以保证木头鸭子不会飞了,看样这问题已经解决了,但是,这时出现了很多代码的重复,我们要对每一个特殊的鸭子进行编程,也就是看看是不是需要重载一些行为。我们可能需要覆盖点很多的行为,这简直就是噩梦。

  这时我们想到了使用接口,把fly放到一个Flyable接口中,这样我们就可以让需要飞翔的鸭子继承这个接口,而不需要的就不用继承这个继承接口了,看似非常的完美。但是,这就造成了没法复用的代码,比如说,如果有一百个鸭子的飞翔行为是相同的,我们就要在这个一百种鸭子中写一百遍相同的代码,这又是一个噩梦的开始。

  这时我们想到了OO设计原则中的一条:“找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码放到一块(OO设计原则1)”。现在我们需要分出需要变化的fly行为来,把它和鸭子这个类分离开来,这时我们会想到OO设计原则中的一条“针对接口编程,而不是针对实现编程(OO设计原则2)”。也就是说,我们可以利用FlyBehavior接口把需要变化的fly封装起来,然后针对这个接口进行编程,而不是针对每一个鸭子进行编程。所以我们完成了对fly的设计

public interface FlyBehavior{

public void fly();

}

public class FlyWithWings:FlyBehavior{

public void fly(){

//会飞的鸭子

}

}

public class FlyNoWay:FlyBehavior

{

public void fly(){

//不会飞的鸭子

}

}
public class Duck
{
FlyBehavior flyBehavior;
void PerformaceFly
{
flyBehavior.fly();
}
}
pulbic class HeadDuck:Duck
{
HeadDuck()
{
flyBehavior=new FlyWithWings();
}
}
public class WoodDuck:Duck{
WoodDuck()
{
flyBehavior=new FlyNoWay();
}
}

这样,我们就可以比较完整的设计鸭子这个类了。

这里我们仅仅就原理进行展示,我的例子将以完整代码形式呈现。

其实上面就是策略模式的使用:定义了算法簇,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。就像上面的鸭子的行为,我们可以把它理解为是鸭子的一些算法,这样,这些行为就构成了一些算法簇,所有,也就是我们说的策略模式。

除此之外,还有一个设计原则:多用组合,少用继承。

Duck.rar

原文地址:https://www.cnblogs.com/lufangtao/p/2454202.html