最近在做一个轻量级CMS供客户站点使用。
根据客户的需求,需要以静态页方式提供用户浏览的页面,同时还要保留一个本份,支持“双远程”发布,即在一台远程发布服务器上保留存根,最终页面保存在文件服务器上供用户访问。
研究了半天,发现可以用策略模式和职责链模式相结合来实现这个处理逻辑(我估且称此为策略链模式)。
以下是策略链的根接口,其他接口从这上面继承:
1namespace strategyChain
2{
3 public interface IStrategy<T>
4{
5 T Next{get;}
6}
7}
2{
3 public interface IStrategy<T>
4{
5 T Next{get;}
6}
7}
处理新闻的接口:
1namespace strategyChain
2{
3 public class News
4{}
5
6 public interface INewsStrategy : IStrategy<INewsStrategy>
7{
8 void DoSomething(News news);
9}
10}
2{
3 public class News
4{}
5
6 public interface INewsStrategy : IStrategy<INewsStrategy>
7{
8 void DoSomething(News news);
9}
10}
然后写一个抽象类来实现该接口:NewsStrategy
namespace strategyChain
{
public abstract class NewsStratey : INewsStrategy
{
protected INewsStrategy next;
public NewsStrate(INewsStrategy next)
{
this.next = next;
}
public virtual void DoSomething(News news)
{
if(next != null)
{
next.DoSomething();
}
}
}
}
{
public abstract class NewsStratey : INewsStrategy
{
protected INewsStrategy next;
public NewsStrate(INewsStrategy next)
{
this.next = next;
}
public virtual void DoSomething(News news)
{
if(next != null)
{
next.DoSomething();
}
}
}
}
为了满足顾客的要求,写了三个类来继承NewsStrategy: LocalNewsStrategy,RemoteNewsStrategy,SqlNewsStrategy
1namespace strategyChain
2{
3 public class LocalNewsStrategy : NewsStrategy
4{
5 public LocalNewsStrate(INewsStrategy next) : base(next){}
6
7public override void Dosomething(News news)
8{
9 localDo(news);
10 base.DoSomething(news);
11}
12}
13
14private void localDo(News news)
15{
16//todo:本地操作逻辑
17}
18}
2{
3 public class LocalNewsStrategy : NewsStrategy
4{
5 public LocalNewsStrate(INewsStrategy next) : base(next){}
6
7public override void Dosomething(News news)
8{
9 localDo(news);
10 base.DoSomething(news);
11}
12}
13
14private void localDo(News news)
15{
16//todo:本地操作逻辑
17}
18}
1namespace strategyChain
2{
3 public class RemoteNewsStrategy : NewsStrategy
4{
5 public RemoteNewsStrategy(INewsStrategy next)
6:base(next){
7
8}
9
10public override void DoSomething(News news)
11{
12 remoteDo(news)
13 base.DoSomething(news);
14}
15
16private void remoteDo(News news)
17{
18 //执行远程逻辑
19}
20}
21}
2{
3 public class RemoteNewsStrategy : NewsStrategy
4{
5 public RemoteNewsStrategy(INewsStrategy next)
6:base(next){
7
8}
9
10public override void DoSomething(News news)
11{
12 remoteDo(news)
13 base.DoSomething(news);
14}
15
16private void remoteDo(News news)
17{
18 //执行远程逻辑
19}
20}
21}
1namespace strategyChain.SqlClient
2{
3 public class SqlNewsStrategy : NewsStrategy
4{
5 public SqlNewsStrategy(INewsStrategy next):base(next){}
6
7public override void DoSomething(News news)
8{
9 sqlDo(news);
10 base.DoSomething(news);
11}
12
13private void sqlDo(News news)
14{
15 //执行数据库逻辑
16}
17}
18}
2{
3 public class SqlNewsStrategy : NewsStrategy
4{
5 public SqlNewsStrategy(INewsStrategy next):base(next){}
6
7public override void DoSomething(News news)
8{
9 sqlDo(news);
10 base.DoSomething(news);
11}
12
13private void sqlDo(News news)
14{
15 //执行数据库逻辑
16}
17}
18}
把这个写完了以后,创建一个NewsProvider类,来根据用户定义配置稿件的操作逻辑,配置完以后应用程序利用工厂方法,在运行时得到一个NewsProvider,来执行策略链。工厂方法在这里就不写了,写一个NewsProvider的实现。
namespace strategyChain
{
public abstract class NewsProvider
{
protected INewsStrategy strategy;
public NewsProvider()
{
strategy = new RemoteNewsStrategy(null);
strategy = new LocalNewsStrategy(strategy)
}
public void DoSomething(News news)
{
strategy.DoSomething(news)
}
}
}
{
public abstract class NewsProvider
{
protected INewsStrategy strategy;
public NewsProvider()
{
strategy = new RemoteNewsStrategy(null);
strategy = new LocalNewsStrategy(strategy)
}
public void DoSomething(News news)
{
strategy.DoSomething(news)
}
}
}
写完了这个抽象类以后,再在最后一个结点处继承该抽象类:
1namespace strategyChain.SqlClient
2{
3 public class SqlNewsProvider : NewsProvider
4{
5//这个类只要将sqlNewsStrategy加入到策略链就行了,其他的什么都不用做.
6 public SqlNewsProvider()
7{
8 strategy = new SqlNewsStrategy(strategy);
9}
10}
11}
2{
3 public class SqlNewsProvider : NewsProvider
4{
5//这个类只要将sqlNewsStrategy加入到策略链就行了,其他的什么都不用做.
6 public SqlNewsProvider()
7{
8 strategy = new SqlNewsStrategy(strategy);
9}
10}
11}
最后只需要在配置文件中指定 NewsProvider = "SqlNewsProvider"即可,真正的运行时代码将是
News news = null;
//实现news
NewsProvider provider = NewsFactory.GetNewsProvider();
provider.DoSomething(news);