zoukankan      html  css  js  c++  java
  • 学习设计模式之Strategy

      颠颠儿跑到书城,弄了本《软件架构设计》,打算好好学习一下这方面的知识

      有一个章节关于恶性依赖的讲述非常精彩:
       “
       需求改变了,原先的良性依赖变成了恶性依赖,但我们“只受一次愚弄”。比如,在开发一个需求跟踪工具的时候,起初可能仅需要支持保存为专有格式的“项目”文件,但后来又需要导出为HTML格式的网页。
      按照敏捷软件开发过程,来讲述这个故事。
      最开始的设计如下图所示,CReqMartixDoc调用CProjectSaver来保存自己。此时,所有需求就是支持“保存为专有格式的项目文件”,而且我们并没有预见到将来还需要以更多的形式保存,所以类CProjectSaver此时是“不易变的”,CReqMartixDoc对CProjectSaver的依赖是良性依赖,整个设计也是个“稳定的”设计。顺便说明,按照开放-封闭原则(Open-Closed Principle),这并不是一个好的设计;但按照当前的需求,这个设计却“不多不少”刚刚好,因为当前它是满足良性依赖原则的。


    良性依赖 

      后来需求发生了变化,这个工具需要支持“导出为HTML格式的网页”的特性。是的,这个需求不管是客户新提出来的,还是设计人员在上一个迭代有意忽略了,总之在这个迭代周期需求发生了变化。于是,设计人员意识到,需求跟踪工具可能需要支持多种保存策略;如果不改变原来的设计,那么CProjectSaver就是“易变的”,因为它要支持不只一种新的保存策略。好了,如下图所示,设计虽然没有改变,但由于需求的改变,原来设计中的良性依赖,现在变成了恶性依赖,这意味着CReqMartixDoc可能也要随着CProjectSaver的改变而改变,这不是一个灵活的设计。

    恶性依赖

      是的,代码出现了臭味(Smell),需要重构(Refactoring)。让我们谨遵Martin Fowler的教诲——不要将重构和添加新功能同时进行——这一步我们仅进行重构。我们要做的就是去除这个恶性依赖,采用依赖倒置原则(Dependency-Inversion Principle)惯用的“用两个抽象依赖代替一个具体依赖”策略,重构之后的设计如下图所示。我们引入了一个接口CDocSaver,然后让CProjectSaver实现这个接口。一个设计良好的接口无疑是“不易变的”,所以不管是CReqMartixDoc对CDocSaver的调用,还是CProjectSaver对CDocSaver的实现,都是良性依赖。
      重构完毕。


    良性依赖

      哈,新的设计非常易于扩充,我们只需要新写一个CHtmlSaver来实现接口CDocSaver,就离支持“导出为HTML格式的网页”不远了,如下图所示。咦?原来是策略模式。

    策略模式

       Wonderful~~!!!

      看着过瘾,不如实践,从最Easy的方式尝试起是我的习惯。设计这样一个抽象类,它只有一个抽象方法getTextboxColor(),返回一个Color结构的值,但可以有若干的继承类来实现——获取具体的颜色值,come on~

      
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Drawing;

    /// 设计模式演练 
    namespace DesignPattern
    {
        
    /// <summary>
        
    /// 策略模式演练
        
    /// </summary>
        public abstract class GetColor
        {
            
    public abstract Color getTextboxColor();
        }

        
    /// <summary>
        
    /// 实现获取蓝色
        
    /// </summary>
        public class GetBlue : GetColor
        {
            
    public override Color getTextboxColor()
            {
                
    return Color.Blue;
            }
        }

        
    /// <summary>
        
    /// 实现获取红色
        
    /// </summary>
        public class GetRed : GetColor
        {
            
    public override Color getTextboxColor()
            {
                
    return Color.Red;
            }
        }
    }

      在宿主环境类中,就可以灵活的调用,改动无非是实例化时,调用不同的策略代码族~

    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;

    using DesignPattern;

    /// <summary>
    /// 环境类
    /// 运用策略模式调用代码族
    /// </summary>
    public partial class 设计模式_DesignPattern : System.Web.UI.Page
    {
        
    protected void Page_Load(object sender, EventArgs e)
        {

        }

        
    /// <summary>
        
    /// 蓝色策略
        
    /// </summary>
        
    /// <param name="sender"></param>
        
    /// <param name="e"></param>
        protected void btColor_Click(object sender, EventArgs e)
        {
            GetColor getcolor 
    = new GetBlue();

            lblColor.ForeColor 
    = getcolor.getTextboxColor();
        }

        
    /// <summary>
        
    /// 红色策略
        
    /// </summary>
        
    /// <param name="sender"></param>
        
    /// <param name="e"></param>
        protected void btColor2_Click(object sender, EventArgs e)
        {
            GetColor getcolor 
    = new GetRed();

            lblColor.ForeColor 
    = getcolor.getTextboxColor();
        }
    }
  • 相关阅读:
    input 特殊字符限制
    angular $http服务
    angular $resouse服务
    ng-model-options 时延
    Pytorch之数据处理
    python 小顶堆
    刷题套路总结
    数组分成和尽可能相等的子数组
    python3.7 sorted 自定义排序
    Leetcode 二维数组周游 54
  • 原文地址:https://www.cnblogs.com/moye/p/869456.html
Copyright © 2011-2022 走看看