前言
最近从网上看到一句话,模板方法、策略、命令模式都是用来封装算法的,所以我就来总结一下它们三个,废话不多说,上货!
策略模式
策略模式它定义了算法家族,分别封装起来,让它们之间可以互相替换。此模式让算法的变化,不会影响到使用算法的客户。下面是策略模式的结构图:
举个例子:元辰超市十五周年庆,满300减100,不满300则按正常收费。
//抽象算法类
public interface Strategy
{
//算法方法
double AlgorithmInterface(double money);
}
//正常收费
class DaZhe : Strategy
{
public double AlgorithmInterface(double money)
{
return money ;
}
}
//满300打8折
class Man : Strategy
{
public double AlgorithmInterface( double money)
{
if (money>=300)
{
return money * 0.8;
}
else
{
return money;
}
}
}
//上下文
class Context
{
Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
//上下文接口
public double ContextInterface(double money)
{
return strategy.AlgorithmInterface(money);
}
}
客户端代码:
static void Main(string[] args)
{
Context context;
context = new Context(new DaZhe());
Console.WriteLine(context.ContextInterface(100));
context = new Context(new Man());
Console.WriteLine(context.ContextInterface(300));
Console.Read();
}
优点
- 扩展性高,可灵活的扩展行为,符合开闭原则。如果增加一个满500打6折,只需要增加一个Strategy的子类即可。
- 避免了使用多重条件选择语句,充分体现面向对象设计思想。
- 策略之间可以动态替换
缺点
- 客户端需要知道所有的策略类。
- 子类过多,增加系统的复杂性。
模板方法模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义改算法的某些特定步骤。下面是模板方法模式的结构图:
举个栗子:我们现在中午和晚上回家做饭,我的菜系有:蒜薹炒肉、菜花炒肉、豆角炒肉,可是我发现这几个菜的做法很相似,于是我就写了一个小程序!
abstract class Vegetabel
{
public void ChaoCai()
{
this.DaoYou(); //倒油
this.FangRou(); //放肉
this.Cong(); //放葱
this.FanChao(); //翻炒
this.FangCai(); //放菜
this.FanChao(); //翻炒
}
//放油
public void DaoYou()
{
Console.WriteLine("倒油");
}
//放葱
public void FangRou()
{
Console.WriteLine("放肉");
}
//放肉
public void Cong()
{
Console.WriteLine("放葱");
}
//放菜的抽象方法
public abstract void FangCai();
//翻炒
public void FanChao()
{
Console.WriteLine("翻炒");
}
}
//蒜薹
class SuanTai :Vegetabel
{
public override void FangCai()
{
Console.WriteLine("把蒜薹放进锅中");
}
}
//菜花
class CaiHua : Vegetabel
{
public override void FangCai()
{
Console.WriteLine("把菜花放进锅中");
}
}
//豆角
class DouJiao : Vegetabel
{
public override void FangCai()
{
Console.WriteLine("把豆角放进锅中");
}
}
客户端代码
优点
- 最大的优点就是实现了代码的复用。
- 灵活已扩展,如果增加一种相似的菜,直接继承Vegetabel即可。
- 符合单一职责原则和开闭原则。
缺点
- 引用一个抽象类,如果具体实现过多的话,会导致系统复杂,混乱
命令模式
讲一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。对请求排队或记录请求日志,以及支持可撤销的操作。下面是命令模式的结构图:
举个栗子:班主任要找XXX来办公室,首先给班长下命令,让XXX来办公室,班长把命令传达过去。老师就是客户端,班长就是命令的请求者,学校就是命令的接受者。
//命令抽象类
abstract class Command
{
protected Receiver receiver;
public Command(Receiver receiver)
{
this.receiver = receiver;
}
//执行方法
abstract public void Action();
}
class ConcreteCommand : Command
{
public ConcreteCommand(Receiver receiver)
:
base(receiver) { }
public override void Action()
{
receiver.Jiao();
}
}
//命令接收者 学生
class Receiver
{
public void Jiao()
{
Console.WriteLine("叫XXX来办公室");
}
//命令请求者 班长
class Invoker
{
private Command command;
public Invoker(Command command)
{
this.command = command;
}
public void ExecuteCommand()
{
command.Action();
}
}
客户端代码:
//老师
static void Main(string[] args)
{
//实例化 学生
Receiver r = new Receiver();
//实例化 具体命令类
Command c = new ConcreteCommand(r);
//实例化 班长
Invoker i = new Invoker(c);
i.ExecuteCommand();
Console.Read();
}
优点
- 降低系统耦合度,将请求者和接收者分开。
- 可以多个命令。
缺点
- 多了一层传递,增加系统的复杂性
- 不符合开闭原则
总结
学习是一个反复的过程,如果再这个反复的过程中不去总结,效果肯定是不一样的。记是永远记不住的,总结了才是自己的。