经过上一次的改造,鸭子类不是靠继承行为接口而拥有行为,而是靠调用者指定行为的方式。例如:指定叫声的形式和飞的形式。保留了灵活性,将权利交给调用者,鸭子本身不再负责行为的初始化。具体的行为表现交给指定的行为方式处理。如果需要有新的行为方式定义,只要实现行为的接口,然后给鸭子指定新定义的行为方式即可。
就像上一回的例子中,将几个类结合起来使用,这就是组合composition。这种做法和“继承”不同的地方就是,鸭子的行为不是继承来的,而是和适当的行为对象“组合”来的。
这就是第三个设计原则:
多用组合,少用继承。
使用组合使系统具有很大的弹性,可以在运行的时候动态指定行为,只要行为是符合标准的接口即可。当然,组合也不是万能的,没有银弹,在后面会讲到它的优缺点。
这种设计使得行为成为一个族群,一个算法群,可以使用里面的任何一个实现来替换。
恭喜你,你已经在使用设计模式了。也就是策略模式(Strategy Pattern),不用怀疑,你正在使用策略模式改进你的代码。
策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
关于继承和组合的一点个人想法:
我认为继承适合用在继承属性上面,例如外观、长相、显示、拥有的物品之类的。如果是行为之类的,就不适合用继承了,适合使用组合。因为继承会使得所有继承类都拥有了相同的行为方式,可能会不是想要的结果。使用组合可以灵活的定义行为、扩展行为,把行为的权力交给了初始化对象的调用者,调用者可以自己选择或者是扩展行为的方式。
设计谜题
内容:一个游戏场景,游戏中各种角色,还有各种武器。角色可以使用武器,每次只能使用一个武器,但是在游戏的过程中可以更换武器。
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BeautyCode.DesignPattern.Head.First
{
public interface IWeaponBehavior
{
void UseWeapon();
}
public class KnifeBehavior : IWeaponBehavior
{
public void UseWeapon()
{
throw new NotImplementedException();
}
}
public class BowAndArrowBehavior : IWeaponBehavior
{
public void UseWeapon()
{
throw new NotImplementedException();
}
}
public class AxeBehavior : IWeaponBehavior
{
public void UseWeapon()
{
throw new NotImplementedException();
}
}
public class Sword : IWeaponBehavior
{
public void UseWeapon()
{
throw new NotImplementedException();
}
}
public abstract class Character
{
private IWeaponBehavior _weapon;
public IWeaponBehavior Weapon
{
get { return _weapon; }
set { _weapon = value; }
}
public void Fight()
{
_weapon.UseWeapon();
}
}
public class King:Character
{
}
public class Queen : Character
{
}
public class Knight : Character
{
}
public class Troll : Character
{
}
}
调用代码
king.Weapon = new Head.First.Sword();
king.Fight();
这个例子也是对前面的一个练习和巩固。关于对象的创建,可以重构为在第一片《深入浅出设计模式-中文版》读书笔记(一) 中讲解的简单工厂来实现。
如何使用设计模式
设计模式不会直接进入你的代码中,而是先进入你的大脑。首先要对设计模式有一个概念的理解,关于模式的原理,可以解决的问题,应用的场景,模式的代码结构等等。然后才能在设计新模块的时候,合适的引入模式,并且在以前的代码变得一团糟而没有弹性的时候,可以重构它们,重构到模式。
良好的OO需要具备:可复用性、可扩充性、可维护性。
模式不是代码,而是针对设计问题的通用解决方案。你可以把他们应用到特定的应用中。
我们通常会把系统中变化的部分抽出来封装。
OO基础
- 抽象
- 封装
- 多态
- 继承
OO原则
- 封装变化
- 多用组合,少用继承
- 针对接口编程,不针对实现编程
OO模式
- 策略模式-定义算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。