基本需求:根据三边a、b、c求三角形周长。
基本抽象:一个三角形类Triangle,有一个求周长的方法GetCirByABC();
基本实现:
public class Triangle
{
public double GetCirByABC(double a, double b, double c)
{
return a + b + c;
}
}
基本不足:依照OO的抽象不应依赖细节,显然a、b、c以及返回值都定位到相应的属性了,违背了抽象不依赖细节原则,故应直接返回一个Triangle对象,他的好处之一就是需要什么值就通过属性来取相应的值,好处之二后面会提到。
改进后的实现:
public class Triangle
{
public double A { get; set; }
public double B { get; set; }
public double C { get; set; }
public double Cir { get; set; }
public Triangle GetModel(Triangle tg)
{
tg.Cir = tg.A + tg.B + tg.C;
return tg;
}
}扩展需求:根据A和B边以及Cir周长求C边长度,看似直接增加一个方法即可解决。
public Triangle GetModel(Triangle tg)
{
tg.C = tg.Cir - tg.A - tg.B;
return tg;
}可以观察到直接返回对象的好处二,不变的是抽象,只是算法发生了变化,由此策略模式应运而生。
策略模式(Strategy):他定义了一系列的算法,并将每一种算法封装起来,并且可以相互替换,新的算法诞生不会造成类结构的破坏,只是一种扩展而已。
策略抽象类定义:
abstract class Strategy
{
public abstract Triangle GetModel(Triangle tg);
}2个具体策略类定义CirByABCStrategy和CByCirABStrategy:
//根据周长和AB边求C
class CByCirABStrategy:Strategy
{
public override Triangle GetModel(Triangle tg)
{
tg.C = tg.Cir - tg.A - tg.B;
return tg;
}
}//根据ABC求周长
class CirByABCStrategy:Strategy
{
public override Triangle GetModel(Triangle tg)
{
tg.Cir = tg.A + tg.B + tg.C;
return tg;
}
}上下文类Context(保存一个策略类的引用)定义:
class Context
{
private Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
public Triangle ContextInface(Triangle tg)
{
return strategy.GetModel(tg);
}
}客户端求周长调用例子:
Triangle triangle = new Triangle();
triangle.A = 3;
triangle.B = 4;
triangle.C = 5;
Context context = new Context(new CirByABCStrategy());//这里决定调用具体的策略类,如果是根据AB和Cir来求则为new CByCirABStrategy();
Triangle tg = context.ContextInface(triangle);
Console.WriteLine("策略模式求周长:" + tg.Cir);
策略模式缺点:实施起来较复杂,如有N种设备,每种设备都存在这样的多种算法情况,可能某些设备存在三四种算法,那类的数量将是很大的。没有完美的设计只有适合的设计。