说明:本次内容大部分来自这本书中。博主只是在看书后,关上书本,重新实现一遍,巩固知识。
设计模式就是一些普遍问题的解决方案。
首先说下书中的前三个设计原则
一 、将对象类中容易发生改变的地方提取出来,进行封装。
二、针对接口编程,而不是对象。
三、多用组合,少用继承。
下面就具体例子来进行说明。
我们针对鸭子来进行设计一个项目,实现一个鸭子的功能。首先分析一下,鸭子肯定都会游泳(天性)。
然后后面需求发生了变化(项目中经常遇到),有的鸭子可能会飞,有的鸭子不能飞,有的鸭子可以飞很快,有的鸭子可能飞不高。。。。同样,鸭子会叫,嘎嘎叫,但是有些鸭子又不能叫(不要纠结原因,可能哑巴了呢?) 。
如果按照以往,我们可能有以下两个方法:
方法一:我们可能就是设计一个基本的鸭子类,Duck,实现3个公共方法,swim(),quack(),fly().然后具体的实现类继承基类,实现方法,现在问题是:飞的方式可能会改变,多种多样,如果这样设计,那么,后面如果需求改变了(鸭子飞的模式改变了),那么,多整个程序的修改是灾难性的,而且容易出错。
方法二:我们将飞行方法提取出来,设计成接口。然后具体的鸭子实现飞行接口就行,但是这样同样有个问题,如果一个对象声明了100次,同样这个对象的飞行方法后面需求发生了改变,那么,同样的要修改100个地方,想想就觉得恐怖。(这里用到了前面设计原则的第一条和第二条)
怎么解决?
策略模式告诉你一些新的经验,解决这些问题。
第一步:将改变的地方,提取出来。
鸭子的飞行方法和嘎嘎叫方法,提出来。
第二步:针对接口编程,而不是对象。
将飞行方法和嘎嘎叫方法设计成接口。如下:
/// <summary>
/// 飞行接口
/// </summary>
public interface IFly
{
void fly();
}
/// <summary>
/// 嘎嘎叫方法
/// </summary>
public interface IQuack
{
/// <summary>
/// 嘎嘎叫方法
/// </summary>
void Quack();
}
然后实现飞行接口和嘎嘎叫接口。比如有一个飞的方法类。声明如如下:
/// <summary>
/// 能够飞行的类
/// </summary>
public class CanFly : IFly
{
public void fly()
{
Console.WriteLine("I Can Fly,Great!");
}
}
不能飞的方法
/// <summary>
/// 不能飞的方法
/// </summary>
public class CanNoFly : IFly
{
public void fly()
{
Console.WriteLine("I Can't Fly");
}
}
。。。。。。。
当然还有其他的飞行方法,就不说了。
第三步,使用组合,少用继承。
声明鸭子类,里面包含飞行接口对象和嘎嘎叫对象。
/// <summary>
/// 鸭子基类
/// </summary>
public abstract class Duck
{
/// <summary>
/// 飞行对象
/// </summary>
protected IFly flyBehavor;
/// <summary>
/// 嘎嘎叫对象
/// </summary>
protected IQuack quackBehavor;
/// <summary>
/// 鸭子都会游泳
/// </summary>
public void swim()
{
//your method
}
/// <summary>
/// 实现飞行方法
/// </summary>
public void Fly()
{
this.flyBehavor.fly();
}
public void Quack()
{
this.quackBehavor.Quack();
}
}
好了,万事俱备,现在看具体实现,假如我们现在有一只飞天蓝鸭,特别吊,可以蓝天下飞。
/// <summary>
/// 飞天蓝鸭
/// </summary>
public class FlyBlueDuck : Duck
{
public FlyBlueDuck()
{
flyBehavor = new CanFly();
quackBehavor = new CanNoQuack();
}
}
我们在类初始化里面定义好这种鸭子的飞行方法。然后调用就行。
class Program
{
static void Main(string[] args)
{
//声明一只飞天鸭
Duck flyduck = new FlyBlueDuck();
flyduck.Fly();
flyduck.Quack();
}
}
运行结果:
如果我们想要在运行时修改飞行的方式,比如鸭子受伤了,翅膀坏了,飞不了了,那么我们需要提供一个可以修改飞行方法的入口,具体实现就是在duck类里面添加一个修改飞行接口的变量方法,同样非常简单,具体如下:
/// <summary>
/// 鸭子基类
/// </summary>
public abstract class Duck
{
/// <summary>
/// 飞行对象
/// </summary>
protected IFly flyBehavor;
/// <summary>
/// 嘎嘎叫对象
/// </summary>
protected IQuack quackBehavor;
/// <summary>
/// 鸭子都会游泳
/// </summary>
public void swim()
{
//your method
}
/// <summary>
/// 实现飞行方法
/// </summary>
public void Fly()
{
this.flyBehavor.fly();
}
public void Quack()
{
this.quackBehavor.Quack();
}
/// <summary>
/// 运行时 改变飞行方法
/// </summary>
/// <param name="flybehavor"></param>
public void setFlyMethod(IFly flybehavor)
{
this.flyBehavor = flybehavor;
}
/// <summary>
/// 运行时改变飞行方法
/// </summary>
/// <param name="quackbehavor"></param>
public void setQuackMethod(IQuack quackbehavor)
{
this.quackBehavor = quackbehavor;
}
}
然后调用:
class Program
{
static void Main(string[] args)
{
//声明一只飞天鸭
Duck flyduck = new FlyBlueDuck();
flyduck.Fly();
flyduck.Quack();
flyduck.setFlyMethod(new CanNoFly());
flyduck.Fly();
flyduck.setQuackMethod(new CanNoQuack());
flyduck.Quack();
}
}
运行结果:
棒极了,我们实现了在运行时修改飞行的方式。
当然,我们也可以实现一种火箭鸭,鸭子可以像火箭一样飞行,具体实现方式就是实现飞行接口,实现火箭飞行类,依照上面的方式,很简单就实现了,而且,对其他地方的代码没有任何影响。
好了,我们整个策略模式大概就是这样了。
嗯,巩固的不错。继续努力,下一个模式,学习观察者模式,学会了也写一个。
源码下载:https://download.csdn.net/download/u013944207/10315530