您的位置:首页 > 其它

学了一招半式-策略模式(设计模式)

2012-04-02 11:19 197 查看
博文更新啦。这2天学了一招分享出来,这招式如同 习武之人领悟了上层心法般。
今天说的是设计模式中经常用到的“策略模式”,概念不说,也不想说,什么是概念,概念就是 让大家理解这个东西是什么意思,可是对于编程理论介绍往往没有实践来的一针见血。
请耐心听完我说的话,很多朋友以为OOP就是理解了 继承 多态 封装 就够了,对,我承认这些是需要掌握,但是这是理论,这些理论的本质也需要掌握,比如:很多朋友以为 class A:class B,哇,这就是继承,可是 这个是继承吗?继承的本质是啥?继承的优势是什么?继承带来了什么好处?
就这个问题,我简单介绍下:
继承本质:你要从 内存机制下手,CLR的托管堆中的GC堆和LOAD堆下手,比如父类的字段在什么位置,比如方法表在什么位置,比如在调用方法的时候是调用什么父类的方法还是子类的方法,这些就是本质?
我写过一篇博文,对于这个本质说了一点:http://www.cnblogs.com/IAmBetter/archive/2012/02/22/2363485.html

可是,这是OOP吗,我说了这么一大堆,这些学完了是OOP吗,显然不是?
例子开始:

abstract class Dog
{
/// <summary>
/// 一些狗公有的特性,跑,啃骨头就省略了
/// </summary>
public abstract void Singing();
}

class RedDog : Dog
{
public override void Singing()
{
Console.WriteLine("我是红狗,我会汪汪汪汪叫。。。");
}

}
class BlackDog : Dog
{
public override void Singing()
{
Console.WriteLine("我是黑狗,我会哇哇哇哇叫。。。");
}
}

class PcDog : Dog
{
//可是机器狗不会叫,也继承了怎么办?

}


提示:对,我承认,你利用了 继承 多态 这2个OOP的思想,而且自以为用的还很好,可是问题来了,机器狗不会叫啊,但是也继承了Singing的方法必须实现这个抽象方法,怎么办?
很多朋友遇到了就会把这个 Singing方法抽象出来,比如抽象成一个接口,然后会叫的狗就实现这个接口。好嘞,修改代码。

interface ISinging
{
void Singing();
}
abstract class Dog
{
/// <summary>
/// 一些狗公有的特性,跑,啃骨头就省略了
/// </summary>

}

class RedDog : Dog,ISinging
{
public  void Singing()
{
Console.WriteLine("我是红狗,我会汪汪汪汪叫。。。");
}

}
class BlackDog : Dog,ISinging
{
public  void Singing()
{
Console.WriteLine("我是黑狗,我会哇哇哇哇叫。。。");
}
}

class PcDog : Dog
{
//机器狗不会叫,那么我就不实现接口

}


哇,多完美,我用了接口实现了OOP的设计,可是问题来了?如果今天,我开心,我赋予 所有的狗要回飞,于是你又实现了 一个“IFly”的接口。哪天,我要让狗会跳舞,我还得实现“IDance”接口,依次下去。。。。
看代码:

interface ISinging
{
void Singing();
}
interface IFly
{
void Fly();
}
abstract class Dog
{
/// <summary>
/// 一些狗公有的特性,跑,啃骨头就省略了
/// </summary>

}

class RedDog : Dog,ISinging,IFly
{
public  void Singing()
{
Console.WriteLine("我是红狗,我会汪汪汪汪叫。。。");
}

public void Fly()
{
Console.WriteLine("我会飞");
}

}
class BlackDog : Dog,ISinging,IFly
{
public  void Singing()
{
Console.WriteLine("我是黑狗,我会哇哇哇哇叫。。。");
}
public void Fly()
{
Console.WriteLine("我会飞");
}
}

class PcDog : Dog,IFly
{
//机器狗不会叫,那么我就不实现接口
public void Fly()
{
Console.WriteLine("我会飞");
}

}


对,我承认,你利用了接口是完成了客户的需求,可是如果客户是个变态,他需要100000种狗,那么你这个 Fly方法必须写100000次,好庞大的代码量。

对了,我们说过OOP实现了代码复用,为什么不考虑下能否代码复用呢?

very good 策略模式的本质出现了:把所有的方法抽象出来,类似于你的接口,然后利用复用代码的特点,节省开发,灵活改变。

有点领悟没?就是说,你的接口实现,比如一个需求来了,你是为了 完成这个需求(设计)而写代码,这是解决方法,不是思想,而OOP思想是为了 接口编程,为了N多设计,为了N多需求,从一定的高度思考设计框架的一个过程。

不说废话,开始写:
思考下:
狗Singing()方法是吧,如果有2种叫法,一种 哇哇叫,一种汪汪叫,那就抽象出来
狗还会飞()方法,比如会 低空飞,高空飞。
把这些会改变的动作抽象出来,把那些不会改变的动作封装起来,一起继承。

/// <summary>
/// 这是所有Sing的叫法
/// </summary>

interface ISingable
{
void Singing();

}

class WAWA_Sing:ISingable
{
public void Singing()
{
Console.WriteLine("我会哇哇叫。。。");
}
}
class wangwang_Sing : ISingable
{
public void Singing()
{
Console.WriteLine("我会汪汪叫。。。");
}
}

/// <summary>
/// 这是所有Fly的飞法
/// </summary>
///

interface IFlyable
{
void Fly();
}
class L_Fly:IFlyable
{
public void Fly()
{
Console.WriteLine("我会低空飞行");
}
}

class H_Fly : IFlyable
{
public void Fly()
{
Console.WriteLine("我会高空飞行");
}

}
abstract class Dog
{
/// <summary>
/// 一些狗公有的特性,跑,啃骨头,是公有的特性不会改变,所以封装起来被继承
/// </summary>
///
protected ISingable isingable;
protected IFlyable iflyable;

public void PerformSing()
{
isingable.Singing();
}

public void PerformFly()
{
iflyable.Fly();
}

}

class RedDog : Dog
{
public RedDog()
{
isingable = new WAWA_Sing();
iflyable = new H_Fly();
}

}
class BlackDog : Dog
{
public BlackDog()
{
isingable = new wangwang_Sing();
iflyable = new L_Fly();
}
}


代码如上:
1.当还有900个不同的狗 要设计的时候,如何飞,如何叫,只要在这个狗的构造函数内 声明下 是什么叫法类型的对象,是什么飞行类型的对象即可---实现了复用
2.对于如果没有会飞的狗或者不会叫的狗,必须在写代码前就考虑好。

这就是策略模式。

不妨大家可以尝试着,用这个模式 遇到什么设计都用这个模式,练习10几天,然后你自然会总结出 他的优势和缺点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: