前进中的蜗牛

番茄大叔

水滴穿石,非一日之功;没有量变,何来质变。

面向对象设计原则

单一职责原则(SRP, Single Responsibility Principle)

定义

一个类,最好只做一件事,只有一个引起它变化的原因。

应用

数据库管理系统为例,通常情况下根据不同的权限进行数据增删改查。
比较坏的设计将判断用户权限和对数据的增删改查放在一个类,在遇到权限或对数据操作修改时都需要修改该类

	public void Add()
		{
			if (GetPermission("userId")=="CanAdd")
			{
				Console.WriteLine("我有权限添加数据");
			}
		}

考虑单一责任原则,将权限判断和对数据操作分到不同的类,通过权限代理实现单一职责

    public interface IDBAction
	{
		void Add();
	}
	public class DBManager: IDBAction
	{
		public void Add()
		{
			//执行数据增加
		}
	}

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

		public string GetPermission(string userId)
		{
			string userRole = string.Empty;
			return userRole;
		}

		public void Add()
		{
			if (GetPermission("userId") == "CanAdd")
			{
				dbManager.Add();
			}
		}
	}

开放封闭原则(OCP, Open Closed Principle)

定义

软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开发的,而对修改是封闭的。

应用

这里实现个计算器,由客户端和计算端组成。设计应该尽量保证计算端的核心业务不修改。坏的代码无法对功能扩展

	public class Client
	{
		private CalculatorProcess _calculator = new CalculatorProcess();

		public int NumFirst { get; set; }
		public int NumSecond { get; set; }
		public int Use(string oper)
		{
			int ret = 0;
			switch (oper)
			{
				case "+":
					ret = _calculator.Add(this.NumFirst, this.NumSecond);
					break;
				case "-":
					ret = _calculator.Sbu(this.NumFirst, this.NumSecond);
					break;
				default:
					break;
			}

			return ret;
		}
	}

	public class CalculatorProcess
	{
		public int Add(int a,int b)
		{
			return a + b;
		}

		public int Sbu(int a,int b)
		{
			return a - b;
		}
	}

对计算端扩展开放,添加乘法

public class Client
	{
		private ICalculatorProcess _calculator;

		public int NumFirst { get; set; }
		public int NumSecond { get; set; }
		public int Use(string oper)
		{
			int ret = 0;
			switch (oper)
			{
				case "+":
					_calculator = new Add();
					ret = _calculator.Operation(this.NumFirst, this.NumSecond);
					break;
				case "-":
					_calculator = new Sub();
					ret = _calculator.Operation(this.NumFirst, this.NumSecond);
					break;
				case "*":
					_calculator = new Mul();
					ret = _calculator.Operation(this.NumFirst, this.NumSecond);
					break;
				default:
					break;
			}
			return ret;
		}
	}

	public interface ICalculatorProcess
	{
		int Operation(int a, int b);
	}

	public class Add : ICalculatorProcess
	{
		public int Operation(int a, int b)
		{
			return a + b;
		}
	}

	public class Sub : ICalculatorProcess
	{
		public int Operation(int a, int b)
		{
			return a - b;
		}
	}

	public class Mul:ICalculatorProcess
	{
		public int Operation(int a, int b)
		{
			return a * b;
		}
	}

依赖倒置原则(DIP, Dependency Inversion Principle)

定义

  • 高层模块不应该依赖于底层模块,二者都应该依赖于抽象。
  • 抽象不应该依赖于具体,具体应该依赖于抽象。

应用

依赖倒置也是著名的好莱坞法则:不要调用我们,我们会调用你。在高层与低层间添加一抽象层(如上面的计算器)。

接口隔离原则(ISP, Interface Segregation Principle)

定义

使用多个小的专门的接口,而不要使用一个大的总接口。
一个类对另一个类的依赖应该建立在最小的接口上,不要强迫依赖不用的方法,这是一种接口污染。

应用

天鹅(Swan)即会游泳又会飞,但是鸭子只会游泳。
强迫鸭子飞

接口隔离,做到最小接口

Liskov替换原则(LSP, Liskov Substitution Principle)

定义

子类必须能够替换其基类。

应用

主要体现在父类方法应该为virtual方法,子类重写父类方法,则子类完全可以替换父类在此调用自己的方法。

posted @ 2018-02-24 13:18  LoveTomato  阅读(266)  评论(0编辑  收藏  举报