六大设计原则浅析
一、设计在软件开发中的重要性重要性在上大学的时候我们总是不理解为什么要讲这么理论性的东西,当时就一个感觉就是没什么用,我们更想去学习一些可以看到结果的东西,当你毕业之后就会发现基础的知识是多么重要,而这些知识都有一个共性就是可以脱离具体的技术或者问题而存在,是一种可以长期指导我们学习和进步的重要思想,设计原则和模式就是软件开发中的这种思想。 设计原则我们先来思考一个问题:
我们来假设一个项目是由某个程序员独立去完成的,他做的事情不仅仅编码这么简单,编写实现功能的代码只占整个项目的30%都不到,他首先做的就应该是对整个项目的技术选择和框架设计(需求的学习和理解暂且不考虑),接下来才是正式编写代码,在实现过程中又需要多次的测试和修改(重构),这样就够了吗?如果能做到这些是可以开发出一个完整的软件,但是还不够。软件工程和盖房子有所区别的地方就在这里,房子盖好就不需要拆了重盖了,软件开发中我们还需要考虑到日后的迭代和变更,所以我们要做到整个结构有一个好的可维护性,设计原则是什么?设计原则就是指导我们实现这种结构的理论基础(也可以说是思想)。 设计模式好了,设计原则有了,我也知道了应该遵循什么原则了,接下来怎么办?我该如何去在实际工程中运用这样的原则?设计模式就是为了解决这些问题而出现的,说白了设计模式就是我们智慧的老前辈们总结出来一些遵循六大设计原则的面向对象的实际应用方式。我们学会了这些设计模式可以使我们更加理解到设计原则的重要性,而设计原则也能帮助我们记忆和灵活应用各种设计模式。 二、六大设计原则单一职责原则
这个原则就是知道我们如何去封装一个对象(或者说如何去划分和定义类),“万物皆对象”这句话表明,任何事物都是对象,如何定义一类事物,完全由我们自己的需要决定。单一职责原则就是说明我们在定义(或者叫划分)一个类的时候应该尽可能的让他做一件事情,看起来这个原则很简单,但是问题恰恰就出在这个简单的“一件事情”上,如何来区分是一件事情就是一个问题?举个例子来说 /** * 电话接口 * @author PeggyTong * */
public interface IPhone {
//拨打电话
public void dial(String phoneNumber);
//通话
public void chat(Object obj);
//挂断电话
public void hangup();
}
上面这接口看起来没有什么问题,它就是做一件事情打电话(看成我们的手机),但是如果我们这里把一件事情定义成单纯的拨打电话,那么它又不是在做一件事情,所以说这里的单一职责要根据我们具体的业务逻辑来定,而不是越小越好的。
其实在软件开发中单一职责不仅仅对于类和接口是这样,对于方法的定义也应该见名知其意(做一件事)。 里氏替换原则(本文出自水寒的CSDN博客:http://blog.csdn.net/dawanganban)
第二个定义是最清晰明确的,通俗点讲,只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或者异常,使用者可能根本不需要知道父类还是子类。但是反过来就不行了,有子类出现的地方,父类未必就能适应。
我们在Java中很容易看到继承的这些特点,如果我们不符合这些特征,编译器会告诉我们错误或警告。 依赖倒置原则
高层模块和低层模块容易理解,每一个逻辑的实现都是由原子逻辑组成的,不可分割的原子逻辑就是低层模块,原子逻辑的再组装就是高层模块。那么什么是抽象?什么又是细节呢?在Java语言中,抽象就是接口或者抽象类,两者都是不能直接被实例化的;细节就是实现类,实现接口或者抽象类而产生的类就是细节,其特点就是可以直接被实例化,也就是可以加上一个关键字new产生一个对象。依赖倒置原则在java语言中的表现是: package cn.org.sunhome.yldz;
//具体的司机
public class Driver implements IDriver{
private ICar mCar;
public Driver(ICar car){
mCar = car;
}
@Override
public void drive() {
mCar.run();
}
}
2、Setter方法传递依赖对象 package cn.org.sunhome.yldz;
//具体的司机
public class Driver implements IDriver{
private ICar mCar;
public void setCar(ICar car){
mCar = car;
}
@Override
public void drive() {
if(mCar == null) return;
mCar.run();
}
}
3、接口声明依赖对象(也叫接口注入)也就是上面的方式 package cn.org.sunhome.yldz;
//司机接口
public interface IDriver {
public void drive(ICar car);
}
依赖倒置原则的本身就是通过抽象(接口或者抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的耦合,我们怎么在项目中使用这个规则呢?只要遵循以下几个规则就可以: 接口隔离原则
上面两个定义其实可以这样理解,我们在建立接口的时候要尽量细化接口,同时接口中的方法要尽量的少。 迪米特法则
如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。 开闭原则
开闭原则的定义已经非常明确地告诉我们软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。什么是软件实体?软件实体包括以下几个部分: public interface IBook {
//书籍有名称
public String getName();
//书籍有售价
public int getPrice();
//书籍有作者
public String getAuthor();
}
//小说
public class NovelBook implements IBook{
private String name;
private int price;
private String author;
public NovelBook(String name,int price,String author){
this.name = name;
this.price = price;
this.author = author;
}
@Override
public String getName() {
return name;
}
@Override
public int getPrice() {
return price;
}
@Override
public String getAuthor() {
return author;
}
}
//书店销售
public class BookStore {
private final static ArrayList bookList = new ArrayList();
static{
bookList.add(new NovelBook("天龙八部",3200,"金庸"));
bookList.add(new NovelBook("巴黎圣母院",5600,"雨果"));
bookList.add(new NovelBook("悲催世界",3500,"雨果"));
bookList.add(new NovelBook("金瓶梅",4300,"兰陵笑笑生"));
}
public static void main(String[] args){
NumberFormat formatter = NumberFormat.getCurrencyInstance();
formatter.setMaximumFractionDigits(2);
System.out.println("----------------书店卖出去的书籍记录如下------------------");
for(IBook book : bookList){
System.out.println("书籍名称:" + book.getName() +
"t书籍作者" + book.getAuthor() + "t书籍价格" +
formatter.format(book.getPrice() / 100.0) + "元");
}
}
}
如果现在书店开始打折销售:所有40元以上的书籍9折销售,其他8折销售,对于这个变化,我们应该如何应对,有三种方法可以解决: 1、修改接口 在IBook上新增一个方法getOffPrice(),专门用于进行打折处理,所有实现类实现该方法。但是这样修改的后果就是,实现类NovelBook要修改,BookStroe中的main方法也修改,同时IBook作为接口应该是稳定且可靠的,不应该经常发生变化,否则接口作为契约的作用失去了效能,因此,该方案否定。 2、修改实现类 修改NovelBook类中的方法,直接在getPrice()中实现打折,但是这个不是好办法,因为如果采购人员要看实际价格就没办法查看了。 3、通过扩展实现变化 增加一个子类OffNovelBook,覆写getPrice()方法,高层次的模块通过OffNovelBook类产生对象,完成业务变化对系统的最小开发,好办法! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |