3.1.软件设计通用原则
3.1.1 内聚和耦合
内聚:建议创建专注类,少量方法表示逻辑操作。
耦合:衡量两个软件模块(如类)之间的依赖程度。例如A类和B类,A类改变,必须改变B,说明它们耦合。
3.1.2 关注点分离(Soc)
有助于实现高内聚低耦合的原则,关注点分离。
Soc建议你只把注意力放在一个具体的关注点上。
3.1.3 隔离
只有公共接口成员才对其他模块可见。内部数据不暴露,要么封装起来,选择性暴露。
接口包含模块行为,细节不可见。
3.2 面向对象设计
OOD定义:
你必须找到相关对象,划分成合适粒度的类,定义类的接口和继承体系,然后在它们之间简历关键关系。
3.2.2 对接口编程
横切关注点:是你需要放在类里却与类的需求没有太大关系的功能。
日志记录、用户验证、多线程、缓存、对象池、错误处理、本地化以及数据验证等。应该是类的一部分吗?还是放在调用类之外更好?
如果作为一部分,横切关注点会带来重复代码的重大风险。
相反,则横切关注点会导致紧密依赖。
完全分离横切关注点需要使用依赖注入(DI)或服务定位器(SL)等模式。一般而言,分离横切关注点意味类是对接口而不是实现编程的。
3.2.3 组合和继承
重用的两个原则:白盒和黑盒重用。
白盒:继承。
黑盒:基于对象组合,需要一个新的类型持有基类型的示例,一般通过私有成员引用它:
public RegisterdUser
{
private User theUser;
public RegisterdUser( )
{
theUser = new User( );
}
}
继承缺点:使用从父类继承而来的上下文的派生类可能因为父类后续更改而坏掉。
保证父类及派生类可以交替使用是“里氏代换原则”的目标。
对象组合是一种防御式编程,更加安全,易于维护与测试。
3.3 开发和设计向量
SOLID 原则:
1.单一职责原则 (SRP)##
一个类,最好只做一件事,只有一个引起它改变的原因。
DBManager
类将对数据库操作和权限判断封装在一个类中,
public class DBManager
{
public void Add()
{
if (GetPremission(id)=="CanADD")
{
Console.WriteLine("管理员可以增加数据。");
}
}
}
如果权限规则改变,那必须重新修改所有数据库操作逻辑。
下面以Proxy模式调整,
public class DBManager:IDBAction
{
public void Add()
{
//执行数据增加
}
}
把权限判断交给DBManagerProxy
public class DBManagerProxy : IDBAction
{
private IDBAction dbManager;
public DBManagerProxy(IDBAction dbAction)
{
dbManager = dbAction;
}
//处理权限判断的逻辑
public string GetPremission(string id)
{
//处理权限逻辑
}
public void Add()
{
if (GetPremission(id)=="CanADD")
{
dbManager.Add();
}
}
}
遵循这个原则的关键,并不是功能点的多少来划分,而是从引起类变化的原因来把握。
2.开放封闭原则 (OCP)##
对扩展开放,对修改关闭。
3.里氏替换原则 (LSP)##
子类必须能替换基类。
4.接口分离原则 (ISP)##
使用多个小的专门的接口,而不要使用一个大而全的总接口。
5.依赖反转原则 (DIP)##
高层模块不能依赖于底层模块,而应该依赖于抽象。
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public void PlayIPhone(Iphone phone)
{
Console.WriteLine("这里是{0}", this.Name);
phone.Call();
phone.Text();
}
public void PlayLumia(Lumia phone)
{
Console.WriteLine("这里是{0}", this.Name);
phone.Call();
phone.Text();
}
public void PlayHonor(Honor phone)
{
Console.WriteLine("这里是{0}", this.Name);
phone.Call();
phone.Text();
}
}
这里手机
与学生
紧耦合状态,最好的办法是
分离接口和实现:高层模块调用接口的方法,低层模块实现接口的定义。
创建抽象类
public abstract class AbstractPhone
{
public abstract void Call();
public abstract void Text();
}
Student类
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public void PlayPhone(AbstractPhone phone)
{
Console.WriteLine("这里是{0}", this.Name);
phone.Call();
phone.Text();
}
}
6.迪米特法则 (LOD)##
最少知识法则,软件实体尽可能与其他实体发生相互作用。(不要和陌生人说话)