设计模式6大原则

1、单一职责

定义:不要存在多于一个导致类变更的原因。通俗的说,即一个程序集、一个类、一个接口、一个方法 最优的设计原则是只负责一项职责。 

核心精神:一个程序集、一个类,或者一个接口,一个方法、最好只做一件事情,当发生变化时,他只能受到单一的影响;因为职责越多,可能引起变化的原因将会越多,这样导致职责和功能上的依赖,将严重影响其内聚性和耦合度,混乱由此而生。

方法职责

混合方法:

        public void WaterMark(string PicturePath, string Word)
        {
            FileInfo fileInfo = new FileInfo(PicturePath);

            switch (fileInfo.Extension)
            {
                case "jpg":
                    ///jpg 处理代码
                    break;
                case "jpep":
                    ///jpep 处理代码
                    break;
                default:
                    break;
            }
        }

单一职责的方法:

        public void WaterMarkJpg(string PicturePath, string Word)
        {
            FileInfo fileInfo = new FileInfo(PicturePath);
            ///jpg 处理代码
        }

        public void WaterMarkJpep(string PicturePath, string Word)
        {
            FileInfo fileInfo = new FileInfo(PicturePath);
            ///jpeg 处理代码
        }

这两种方法有什么优缺点呢?

混合方法:

缺点:修改、增加、如果有错误、会影响到其它全部的职责使用。

优点:扩展的时候、只需要修改方法,调用端不用更改代码。封闭了变化点。

单一职责方法:

优点:增加、修改的时候,只会影响到自己、不会影响到别的职责。

缺点:调用端增加相对应的修改,变化点传递给使用端。

以上对于方法的职责分析中、各有优缺点,使用哪一种方式最好,很难讲。

类职责

类也应该遵守单一职责、

混合职责类,上传和下载

    public class UploadAndDownLoad
    {
        /// <summary>
        /// 文件上传
        /// </summary>
        /// <param name="file"></param>
        /// <param name="path"></param>
        public static void Upload(HttpPostedFile file ,string path)
        {
            file.SaveAs(path);
        }
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static FileStream DownLoad(string path)
        {
            return File.OpenRead(path);
        }
    }

如果有一天我们的需求发生变更,我们需要把上传类改成这样,

  public class UploadAndDownLoad<S> where S:Stream,new()
    {
        /// <summary>
        /// 文件上传
        /// </summary>
        /// <param name="file"></param>
        /// <param name="path"></param>
        public static void Upload(string path,S stream)
        {
            byte[] bufeel = new byte[stream.Length];
            stream.Read(bufeel, 0, 10000);

            File.WriteAllBytes(path, bufeel);
        }
        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static FileStream DownLoad(string path)
        {
            return File.OpenRead(path);
        }
    }

你会发现,下载的调用代码也必须要修改。所以类型一定要在设计的时候遵行单一职责。这样我在修改上传类的功能,不会影响到下载类的功能调用。

程序集:

程序集更应该理顺所有职责,因同样的道理。为了将来的升级维护方便 。

只有你用好了,单一职责,你才会代码清楚、不会产生乱象。这样才可以容易维护。

如果我不分开,只会增加维护难度。

2、里氏替换原则

里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能

原因如下:

1、子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
2、子类中可以增加自己特有的方法。(可以扩展自己的功能)
3、当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
4、当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

子类和父类继承关于方法重写的2种操作。

重载(Overload):方法名称相同,参数、返回值不同 的一组方法,用来动态处理相适配的功能。

重写(Override):覆盖父类的方法,实体方法可以用 new 来重写,虚方法可以用 override 来重写,抽像方法也可以用 override 来重写。

除非必须、尽可能少地重写父类方法,因为子类也会被继承,这在整个体系中会发生混乱。


3、依赖倒置(上端和下端的依赖要通过口、而不是直接实现)

依赖倒置原则,重要的三层含义:

1、高层模块不应该依赖低层模块,两者都应该依赖其抽象;

2、抽象不应该依赖细节;

3、细节应该依赖抽象。

其核心思想是:依赖于抽象。

应用在项目中,实际就是类与类之间的引用、都应该抽象出来、抽象成接口或者是抽象类。类与类之间的引用必须要基于接口或者是抽象类。而不是直接引用

例如:

直接依赖:

    class Mother
    {
        public void narrate(Book reader)
        {
            Console.WriteLine ("妈妈开始讲故事");
            Console.WriteLine(reader.getContent());
        }
    }

    class Book
    {
        public string getContent()
        {
            return "很久很久以前有一个阿拉伯的故事……";
        }
    }

依赖倒置:

    class Mother
    {
        public void narrate(IReader reader)
        {
            Console.WriteLine ("妈妈开始讲故事");
            Console.WriteLine(reader.getContent());
        }
    }

    public interface IReader
    {
        string getContent();
    }

    class Book: IReader
    {
        public string getContent()
        {
            return "很久很久以前有一个阿拉伯的故事……";
        }
    }

1、Mother类与Book类并不是直接依赖使用的,而是通过IReader接口来依赖。

2、如果有一天,增加其它读物,比如NEWSPAPER,报纸类。只需要

    class NewsPaper : IReader
    {
        public string getContent()
        {
            return "很久很久以前有一个阿拉伯的故事……";
        }
    }

这就充分符合,开闭原则,对扩展开放,对修改封闭。(我要增加一个新的功能,我只需要增加一个类就OK了,并不需要对原有的类进行修改)

 

4、接口隔离原则

定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。 

(接口也需要单一职责、尽可能把接口的功能分开,最小化设计)也不需要一个方法一个接口、这种过份了。只需要一类功能放在一个接口里面

抽像是稳定的,细节是多变的。接口要稳定

5、迪米特法则
高内聚、自己的事尽量自己完成。
低耦合、我们之间相互依赖尽量减少。
接口统一、功能封闭

只关心自己的职责、只对依赖负责

增加功能是扩展、修改代码是修改。

 

一个类尽可能少的与外界发生关联。

 

6、开闭原则

 

问题由来:在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。

解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

说到这里,再回想一下前面说的5项原则,恰恰是告诉我们用抽象构建框架,用实现扩展细节的注意事项而已:

单一职责原则告诉我们实现类要职责单一;

里氏替换原则告诉我们不要破坏继承体系;

依赖倒置原则告诉我们要面向接口编程;

接口隔离原则告诉我们在设计接口的时候要精简单一;

迪米特法则告诉我们要降低耦合。

而开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭。

 

参考资料: 

http://www.uml.org.cn/sjms/201211023.asp

http://jingyan.baidu.com/article/6525d4b13aed08ac7c2e947f.html

转载于:https://www.cnblogs.com/lystory/p/5584531.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值