策略模式-定义了算法族,分别封装起来,让它们相互之间可以替换。
对于客户的可能变化的行为采用组合的方式而非继承的方式。组合可以更加灵活的使用,而继承应对接口变化时太过繁琐。
下面用代码说明:
先定义一个抽象基类Car,所有实体车都要继承这个抽象基类
public abstract class Car
{
//能跑
public void Run()
{
Console.WriteLine("i can run");
}
//打印品牌
public abstract void Brand();
}
定义奔驰、宝马
public class Benz : Car
{
public override void Brand()
{
Console.WriteLine("奔驰");
}
}
public class Bmw:Car
{
public override void Brand()
{
Console.WriteLine("宝马");
}
}
现在奔驰要装倒车雷达,但是宝马不装(说不定以后要装,甚至还要装全身雷达)。
方案1:建立一个雷达接口,Car继承。但是这会让每辆车都有一个雷达。可以在每个实体类中重写,但是后期需求改变,就得改这个类了。
方案2:建立一个雷达接口,由实体类继承。也不太好,原因和上面一样。
方案3:建立一个雷达接口,不在用继承的方式,而采用组合的方式。不需要在类中具体实现,可以在外部实现接口,做到松耦合。
接下来采用方案三来重写。
public interface IRadar
{
void Radar();
}
public abstract class Car
{
public IRadar Radar{ get; set; }
//能跑
public void Run()
{
Console.WriteLine("i can run");
}
//打印品牌
public abstract void Brand();
//展示雷达
public void Perform()
{
Radar.Radar();
}
}
实现雷达实体类
public class NoRadar : IRadar
{
public void Radar()
{
Console.WriteLine("我没有雷达");
}
}
public class ParkingRadar : IRadar
{
public void Radar()
{
Console.WriteLine("我是倒车雷达");
}
}
public class GeneralRadar : IRadar
{
public void Radar()
{
Console.WriteLine("我是全身雷达");
}
}
public class Benz : Car
{
//默认没有雷达
public Benz()
{
Radar = new NoRadar();
}
public override void Brand()
{
Console.WriteLine("奔驰");
}
}
public class Bmw:Car
{
public Bmw()
{
Radar = new NoRadar();
}
public override void Brand()
{
Console.WriteLine("宝马");
}
}
调用
class Program
{
static void Main(string[] args)
{
Car benz = new Benz();
benz.PerformRadar();
//给奔驰加上雷达
benz.Radar = new ParkingRadar();
benz.PerformRadar();
Car bmw = new Bmw();
bmw.PerformRadar();
Console.ReadLine();
}
}
结果
我们默认奔驰和宝马初始都是没有雷达的,这不太好,可能现在倒车雷达成标配了,出厂就自带,所以我们把默认的不带雷达要改成倒车雷达,随着需求的改动,我们需要不断的改变我们的实体类,这又不太好了。所以我们改成创建时决定
修改宝马和奔驰
public class Benz : Car
{
public Benz(IRadar radar)
{
Radar = radar;
}
public override void Brand()
{
Console.WriteLine("奔驰");
}
}
public class Bmw:Car
{
public Bmw(IRadar radar)
{
Radar = radar;
}
public override void Brand()
{
Console.WriteLine("宝马");
}
}
调用
static void Main(string[] args)
{
Car benz = new Benz(new ParkingRadar());
benz.PerformRadar();
Car bmw = new Bmw(new GeneralRadar());
bmw.PerformRadar();
Console.ReadLine();
}
结果
出厂自带,想升级也十分方便,将Rador改成全身雷达即可
在策略模式下,我们的车不论有没有雷达,安装什么雷达,我都不关心了,你决定有就有,你决定没有就没有,我只要调用PerformRador即可,是不是很方便。
当然,如果你想新增加一套自动驾驶系统,我们的实体类的代码是肯定需要改的,但是方法和雷达一样,只需要再添加一个自动驾驶的接口即可。一旦建立了自动驾驶的策略,在自动驾驶领域,无论怎么变,我都不会变。