面向对象基本原则

设计模式是为了让程序具有更好的

代码重用性、可读性、可拓展性、可靠性、使程序呈现高内聚,低耦合的特性。

如果软件系统过于简单,则不必要去为了OO而去OO。

1、 单一责任原则:一个类只负责一项职责

1)降低了类的复杂度,一个类只负责一项职责。

2)提高类的可读性,可维护性。

3)降低变更引起的风险。

4)通常情况下我们应该遵守单一职责原则;只有类中的方法特别少的时候,可以在方法级别保持单一职责原则。

    public class RoadVehicle
    {
        public void Run(string vehicle)
        {
            Console.WriteLine(vehicle + "在公路上运行!");
        }
    }
    public class RiverVehicle
    {
        public void Run(string vehicle)
        {
            Console.WriteLine(vehicle + "在河中运行!");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            RoadVehicle rv = new RoadVehicle();
            rv.Run("汽车");
            RiverVehicle riv = new RiverVehicle();
            riv.Run("");
            Console.Read();            
        }
    }
在类这一层级上遵守单一
    public class Vehicle
    {
        public void RunAtRoad(string vehicle)
        {
            Console.WriteLine(vehicle + "在公路上运行!");
        }
        public void RunInRiver(string vehicle)
        {
            Console.WriteLine(vehicle + "在河中运行!");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Vehicle vhcl = new Vehicle();
            vhcl.RunAtRoad("汽车");
            vhcl.RunInRiver("");
            Console.Read();            
        }
    }
在类中的方法上遵守单一

 当类中的方法较少的时候,可以考虑在方法上遵守单一职责。(在方法上遵循单一,并不是一个标准的处理方式)。

使用Proxy模式,实现单一职责原则:

没有遵循单一职责原则的例子:
        /// <summary>
        /// 假定,该方法对数据库进行insert操作。
        /// </summary>
        public void Add()
        {
            //权限判断的职责和数据库操作的职责被无礼的实现在一个类中,权限的规则变化和数据库操作的规则变化,都有可能引起DBManager修改当前代码。
            if (GetPermission(id) == "CanAdd")
            {
                Console.WriteLine("管理员可以增加数据");
            }
        }

使用代理模式对代码进行调整后,有效地实现了职责分离。
    interface IDBAction
    {
        void Add();
        bool Delete();
        void View();
    }

    //DBManager 只负责数据的处理。
    public class DBManager : IDBAction
    {       
        public void Add()
        {
            //执行数据增加
        }

        public bool Delete()
        {

            return false;
        }

        public void View()
        {

        }
    }

    public class DBManagerProxy : IDBAction
    {
        private IDBAction dbManager;
        public DBManagerProxy(IDBAction dbAction)
        {
            dbManager = dbAction;
        }

        /// <summary>
        /// 处理权限判断的逻辑
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public string GetPermission(string id)
        {
            //处理权限判断。
            return "CanAdd";
        }

        public void Add(string id)
        {
            if (GetPermission(id) == "CanAdd")
            {
                dbManager.Add();//调用了DBManager中的Add方法。
            }
        }
        //通过代理,将数据操作和权限判断两个职责进行分离,而实际的数据操作由DBManager来执行,此时客户端的调用变的非常简单。        

        public bool Delete()
        {
            //部分省略....
            return false;
        }

        public void View()
        {
            //部分省略....
        }
    }
单一职责原则的案例

2、开闭原则

  随着客户需求的变化,只是增加类,而不是修改现有的类。对拓展开放,对修改关闭。

  常用的设计模式:template method,strategy。

不遵循开放封闭原则    
    public class BusyBankStaff
    {
        private BankProcess bankProc = new BankProcess();
        public void HandleProcess(Client client)
        {
            switch (client.ClientType)
            {
                case  "存款用户":
                    bankProc.Deposit();
                    break;
                case "转账用户":
                    bankProc.Transfer();
                    break;
                case "取款用户":
                    bankProc.DrawMoney();
                    break;
            }
        }
    }

使用开放封闭原则,对代码进行重构
    interface IBankProcess
    {
        void Process();
    }

    class DepositProcess : IBankProcess
    {
        public void Process()
        {
            //办理存款业务。
        }
    }

    class TransferProcess : IBankProcess
    {
        public void Process()
        {
            //办理转账业务。
        }
    }

    class DrawMoneyProcess : IBankProcess
    {
        public void Process()
        {
            //办理转账业务。
        }
    }

    class EasyBankStaff
    {
        private IBankProcess bankProc = null;
        public void HandleProcess(Client client) { 
            //办理业务。
            bankProc = client.CreateProcess();
            bankProc.Process();
        }
    }

        static void Main(string[] args)
        {
            EasyBankStaff bankStaff = new EasyBankStaff();
            bankStaff.HandleProcess(new Client("转账用户"));
        }

    class Client
    {
        private string ClientType;
        public Client(string clientType)
        {
            ClientType = clientType;
        }
        public IBankProcess CreateProcess()
        {
            //后期可以通过依赖倒置原则,将下面的语句块给消除。
            switch (ClientType)
            {
                case "存款用户":
                    return new DepositProcess();
                    break;
                case "转账用户":
                    return new DepositProcess();
                    break;
                case "取款用户":
                    return new DepositProcess();
                    break;
            }
            return null;
        }
    }
开放封闭原则的案例

3、依赖倒置原则

 

4、接口隔离原则:客户端不应该依赖它不需要的接口 

5、里氏替换原则

6、迪米特法则(最少知道原则,中介者模式)

  一个类对自己依赖的类知道的越少越好,对于被依赖的类来说,不管有多复杂,都尽量将逻辑封装在类的内部,对外除了提供的public方法,不对外泄露任何信息。

  一个类中,尽量不要突然出现一个局部变量(这个局部变量是另外一个类)。

  只能降低类与类之间的耦合,并不能完全消除类与类之间的耦合。

7、合成复用原则

  尽量使用合成/聚合的方式,而不是使用继承。

如果只是为了使用类中的方法,那么并不是一定需要去继承,可以使用组合的方式(将类的实例传进去)进行方法的调用。

创建型设计模式

  单例模式(Singleton Pattern):把对象的创建权限关闭,提供一个公开的静态方法,起到对象重用的作用。(当对象不会被频繁创建的时候,不建议使用单列,因为这样容易占内存)。

  简单工厂:(不属于GOF的23种设计模式)。

  工厂方法(Factory Method Pattern):每个工厂只负责一个对象的创建。

  抽象工厂(Abstract Factory):每个工厂负责一个产品簇的创建。当多个对象是有机不可分的时候,可以使用抽象工厂来创建多个对象。

  原型模式(Prototype):把对象创建权限关闭,提供一个公开的静态方法,提供全新的对象,不走构造函数。

  建造者模式(Builder):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

结构型设计模式:关注类与类之间的关系。在面向对象中类与类之间进行交互,才能产生功能;纵向关系:继承/实现;横向关系:依赖、关联、组合、聚合。(关系依次变强)。

  适配器模式(Adapter Pattern):在原类型不变的情况下,拓展新的接口。类适配器、对象适配器。

  桥接模式(Bridge Pattern):把实现和逻辑分开,面向对象聚合复用的思想。

  组合模式(Composite Pattern):不管是个体还是组件,都包含公共的操作接口,通过同样的方式来处理一个组合中的所有对象。组件的典型操作包括:增加、删除、查找、分组和获取子元素等。典型运用:树形结构的数据组织。

  外观模式(Facade Pattern):将表现层和逻辑层分离,封装底层的复杂处理,为用户提供简单的接口。外观模式很多时候是一种系统架构的设计,为复杂系统的解耦,提供了最好的解决方案。

  装饰模式(Decorator Pattern):为原有系统,动态的增加或删除状态和行为,在继承被装饰类的同时包含被装饰类的实例成员。.net 中的stream。

  享元模式(Flyweight)

  代理模式(Proxy Pattern):将复杂的逻辑封装起来,通过代理对象控制实际对象的创建与访问,由代理对象屏蔽原有逻辑的复杂性,同时控制其可访问性。(包一层!)

         代理模式与适配器模式从代码上来看是比较接近的,代理模式是为了对原有的类进行二次封装(可以添加原本没有的功能),适配器是为了兼容。

行为型设计模式:关注行为与对象的分离

  责任链模式(Chain of Responsibility Pattern):一个请求需要多个环节处理,环节还有可能拓展,变化,调整顺序等问题。  

  模板方法模式(Template Method Pattern):在父类中定义模板,然后由子类实现。具体的实现一般由父类定义好算法的骨架,然后将算法的某些步骤委托给子类。典型应用:asp.net 的Page类。

  迭代器模式(Iterator Pattern):foreach集合。

  中介者模式(Mediator):

  解释器模式(Interpreter):

  命令模式(Command Pattern):将请求封装为对象,从而将命令的执行者和责任分开。通常在队列中等待命令。典型的应用:菜单系统。

  观察者模式(Observer Pattern):定义对象间的一种一对多的依赖关系。当一个对象的状态发生变化的时候,所有依赖于它的对象都得到通知并被自动更新。观察者和被观察者的分开,为模块划分提供了清晰的界限。 .net中的委托和事件。

  备忘录模式(Memento):

     状态模式(state)

  策略模式(Strategy Pattern):将易于变化的部分封装为接口,通常Strategy封装一些运算法则,使者能互换。

  访问者模式(Visitor):

posted @ 2019-08-23 17:52  水墨晨诗  阅读(288)  评论(1)    收藏  举报