读书笔记----软件设计原则、设计模式
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/2021Softwarecodedevelopmenttechnology |
|---|---|
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/2021Softwarecodedevelopmenttechnology/homework/11833 |
| 这个作业的目标 | 1.学习了解经典的设计模式及原则 2.总结、归纳曾应用的设计模式及原则以提高自己的编程水平 |
阅读书籍

- 书名:大话设计模式
- 作者: 程杰
- 出版社: 清华大学出版社
- 出版年: 2007-12-1
- 页数: 368
- ISBN: 9787302162063
内容归纳
- 设计模式
![]()
- 设计模式的六大原则:
- 开闭原则(Open Close Principle)
开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。 - 里氏代换原则(Liskov Substitution Principle)
里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。 - 依赖倒转原则(Dependence Inversion Principle)
这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。 - 接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。 - 迪米特法则,又称最少知道原则(Demeter Principle)
最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。 - 单一职责原则(Single Responsibility Principle)
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
部分原则具体说明
单一职责原则(Single Responsibility Principle)
- 问题由来:类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有
可能会导致原本运行正常的职责P2功能发生故障。 - 特点:
- 类的复杂性降低,实现什么功能都清晰明确的定义;
- 可读性提高,复杂性降低;
- 可读性提高,则是可维护性提高;
- 变更引起的风险降低,变更是必不可少的,若接口做好单一原则,对系统的扩展性、维护性都有非常大的帮助;
- 启发:一个类不能负责太多事务!在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离。
- 举例
- 举一个用户信息管理系统的例子,用两种不同的方式写的,一个应用了单一职责原则,一个没用。
public class UserInfo implements IUserInfo {
private String userName;
private String userID;
private String password;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserID() {
return userID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
//修改用户密码
public boolean changePassword(String oldPassword){
System.out.println("密码修改成功...");
return true;
}
//删除用户
public boolean deleteUser(){
System.out.println("删除用户成功...");
return true;
}
}
- 用户管理系统的类图
![]()
此类有设置用户名、设置ID、设置密码、增删改等功能。由图可知,这个类总体上来说有两个功能,一个是储存用户信息;一个是对系统内的用户信息进行管理。这么写也能达到我的目的,但是在后期的修改上会有比较大的问题,假如我要在用户的信息中添加一项属性E-mail那我要对IUserInfo接口进行修改,又假如我要对在管理系统中添加一个查找的功能我又得去修改IUserInfo接口这样当这个用户管理系统复杂以后容易造成逻辑混乱。
其实只要对这个用户管理系统的程序进行一个小小的修善就能让它变的清晰明朗。以下是对此管理系统应用单一职责原则的一个小的改进类图:
![]()
- 单一职责原理的优缺点
- 优点:
分工清晰明朗,做到引起变化的只有一个原因,出错时能快速锁定位置,也利于维护与扩展、代码灵活。 - 缺点:
在比较小的项目中,会造成系统的复杂度增加的情况,类的增多会对运行效率有影响。
开闭原则(Open Close Principle)
- 思想:开放-封闭(Open-Close Principle,OCP)原则的基本思想是:
Open(Open for extension):模块的行为必须是开放的、支持扩展的,而不是僵化的
Closed(Closed for modification):在对模块的功能进行扩展时,不应该影响或大规模影响已有的程序模块
开放封闭原则主要是体现在两个方面:
对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。
对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对类进行任何修改。 - 实现思路:对抽象编程,而不对具体编程,因为抽象相对稳定。让类依赖于固定的抽象,所以对修改就是封闭的。而通过面向对象的继承和多态机制,可以实现对抽象体的继承,通过覆写其方法来改变固有行为,实现新的扩展方法,所以对于扩展就是开放的。对于违反这一原则的类,必须通过重构来进行改善。常用于实现的设计模式主要有模板方法模式(Template Method)和策略模式(Strategy)。而封装变化,是实现这一原则的重要手段,将经常变化的状态封装为一个类。
- 举例
- 以银行业务员为例,没有实现OCP设计的:
public class BankProcess
{
public void Deposite(){} //存款
public void Withdraw(){} //取款
public void Transfer(){} //转账
}
public class BankStaff
{
private BankProcess bankpro = new BankProcess();
public void BankHandle(Client client)
{
switch (client .Type)
{
case "deposite": //存款
bankpro.Deposite();
break;
case "withdraw": //取款
bankpro.Withdraw();
break;
case "transfer": //转账
bankpro.Transfer();
break;
}
}
}
这种设计显然是存在问题的,目前设计中就只有存款,取款和转账三个功能,将来如果业务增加了,比如增加申购基金功能,理财功能等,就必须要修改BankProcess业务类。我们分析上述设计就能发现不能把业务封装在一个类里面,违反单一职责原则,而有新的需求发生,必须修改现有代码则违反了开放封闭原则。如何才能解决这个问题呢?那就是抽象,将业务功能抽象为接口,当业务员依赖于固定的抽象时,对修改就是封闭的,而通过继承和多态继承,从抽象体中扩展出新的实现,就是对扩展的开放。
以下是符合OCP的设计:
//首先声明一个业务处理接口
public interface IBankProcess
{
void Process();
}
public class DeposiProcess:IBankProcess
{
public void Process() //办理存款业务
{
Console.WriteLine("Process Deposit");
}
}
public class WithDrawProcess:IBankProcess
{
public void Process() //办理取款业务
{
Console.WriteLine("Process WithDraw");
}
}
public class TransferProcess:IBankProcess
{
public void Process() //办理转账业务
{
Console .WriteLine ("Process Transfer");
}
}
public class BankStaff
{
private IBankProcess bankpro = null ;
public void BankHandle(Client client)
{
switch (client .Type)
{
case "Deposite": //存款
userProc =new WithDrawUser();
break;
case "WithDraw": //取款
userProc =new WithDrawUser();
break;
case "Transfer": //转账
userProc =new WithDrawUser();
break;
}
userProc.Process();
}
}
这样当业务变更时,只需要修改对应的业务实现类就可以,其他不相干的业务就不必修改。当业务增加,只需要增加业务的实现就可以了。
心得体会
学习设计模式,重要的是掌握几个原则:
1. 单一职责。每个类只实现一个功能,而不要融合太多功能在一个类里
2. 开放封闭原则。对增加开放,对修改关闭(增加功能可以,修。
3. 依赖倒转原则。依赖于抽象(接口或父类),而不依赖于实现(子类)
4. 迪米特法则(模块A只接触和自己有直接关系的模块B,如果模块B和模块C有直接关系,而模块A和模块C,没有,则A调用C,要通过B,而不是直接调用)
设计模式的原则是死的,主要是看我们怎么去运用它。上面举的例子在每个系统的设计中都可以用到。设计模式无处不在,在实际的开发当中,设计模式不能死搬硬套,适当变通,才是使用设计模式的关键,也是难点。因为我的开发实践较少,所以还不能讲出更多的东西,接下来会继续学习。




浙公网安备 33010602011771号