浅析JAVA设计模式(三)
4、接口隔离原则: ISP(Interface Segregation Principle) 客户端不应该依赖它不需要的接口,或者说类的依赖的关系应该建立在最小的接口上。举个例子,直接上代码:
1 interface I { 2 public void method1(); 3 public void method2(); 4 public void method3(); 5 public void method4(); 6 public void method5(); 7 } 8 9 class A{ public void depend1(I i){ i.method1(); } public void depend2(I i){ i.method2(); } public void depend3(I i){ i.method3(); } } class B implements I{ public void method1() { System.out.println("类B实现接口I的方法1"); } public void method2() { System.out.println("类B实现接口I的方法2"); } public void method3() { System.out.println("类B实现接口I的方法3"); } //对于类B来说,method4和method5不是必需的,但是由于接口A中有这两个方法, //所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。 public void method4() {} public void method5() {} } class C{ public void depend1(I i){ i.method1(); } public void depend2(I i){ i.method4(); } public void depend3(I i){ i.method5(); } } class D implements I{ public void method1() { System.out.println("类D实现接口I的方法1"); } //对于类D来说,method2和method3不是必需的,但是由于接口A中有这两个方法, //所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。 public void method2() {} public void method3() {} public void method4() { System.out.println("类D实现接口I的方法4"); } public void method5() { System.out.println("类D实现接口I的方法5"); } } public class Client{ public static void main(String[] args){ A a = new A(); a.depend1(new B()); a.depend2(new B()); a.depend3(new B()); C c = new C(); c.depend1(new D()); c.depend2(new D()); c.depend3(new D()); }
相信大家也看出来了接口I太过臃肿了,实际开发中我们应该尽可能的避免这种现象出现。接口定义尽量细化。针对上面的问题,我们可以采用接口隔离来进行解决接口臃肿的问题。
改造后代码:
1 interface I1 {
2 public void method1();
3 }
4
5 interface I2 {
6 public void method2();
7 public void method3();
8 }
9
interface I3 {
public void method4();
public void method5();
}
class A{
public void depend1(I1 i){
i.method1();
}
public void depend2(I2 i){
i.method2();
}
public void depend3(I2 i){
i.method3();
}
}
class B implements I1, I2{
public void method1() {
System.out.println("类B实现接口I1的方法1");
}
public void method2() {
System.out.println("类B实现接口I2的方法2");
}
public void method3() {
System.out.println("类B实现接口I2的方法3");
}
}
class C{
public void depend1(I1 i){
i.method1();
}
public void depend2(I3 i){
i.method4();
}
public void depend3(I3 i){
i.method5();
}
}
class D implements I1, I3{
public void method1() {
System.out.println("类D实现接口I1的方法1");
}
public void method4() {
System.out.println("类D实现接口I3的方法4");
}
public void method5() {
System.out.println("类D实现接口I3的方法5");
}
61 }
将I接口细化为I1,I2,I3,这样在对这三个接口进行实现的时候,就不会出现多余的方法去实现而不进行任何操作的现象。注意:在对接口进行细化的时候,我们要求做到尽量和依赖类的业务保持一致。我的理解是,尽量不要违背单一职责原则。虽然与单一职责原则相似,但与单一职责不同的是,单一职责注重职责,而接口隔离原则更注重接口的依赖隔离。其次单一职责原则更注重的是约束类,然后再是接口和方法,接口隔离更注重约束接口,对程序架构的构建。
采用接口隔离原则注意几点:
1.接口尽量小,但是要有限度,过度小会造成接口繁多。
2.为依赖的类定制服务,不把依赖类不需要的方法暴露出来。
3.提高内聚,不要过多的与外交互。
5、迪米特法则 :LOD(Law Of Demeter ) 一个类应该对自己需要耦合或者调用的类知道的最少,被调用的类内部是怎么实现的,调用者不需要关心,只需要提供者提供了这些方法,能供调用就可以。
下面这个看下老师点名的例子,这个例子讲的挺通俗的,时间关系我在这就不做重复举例了: http://blog.csdn.net/lajiooo/article/details/6365239
6、开闭原则:OCP(Open Close Principle) 解释为一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。
开闭原则是一个非常虚的原则,前面5个原则是对开闭原则的具体解释 。用一个我在《设计模式之禅(第二版)》第45页的书店的一个例子讲解下:
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<IBook> bookList=new ArrayList<IBook>();
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折销售,该怎么去修改程序呢?我想肯定我们不能去修改接口吧,接口是对外的契约,如果修改接口,那要改的地方实在太多了,风险忒大。最直接的想法可能就是直接去修改getPrice()这个方法,这是一个好主意,但是有一个不好的地方,就是修改getPrice()方法之后,显示出来的是打折之后的价格,原来的价格是显示不出来的,这样就没有对比性了,有没有更好的办法呢?这里,让我们来体验一次开闭原则的好处,通过扩展来实现变化,新增了一个OffNovelBook类,继承自NovelBook,并且重写了getPrice()方法,用这个类来处理打折的小说类书籍,不修改原来的代码。新增的类的代码如下:
1 public class OffNovelBook extends NovelBook {
2
3 public OffNovelBook(String name, int price, String author) {
4 super(name, price, author);
5 }
6
7 @Override
8 public int getPrice() {
9 int selfPrice=super.getPrice();//原价
int offPrice=0;//打折之后的价格,初始化为0
if(selfPrice>4000){
offPrice=selfPrice * 90 / 100;
}
else{
offPrice=selfPrice * 80 / 100;
}
return offPrice;
}
}
public class BookStore {
private final static ArrayList<IBook> bookList=new ArrayList<IBook>();
static{
bookList.add(new OffNovelBook("天龙八部",3200,"金庸"));
bookList.add(new OffNovelBook("巴黎圣母院",5600,"雨果"));
bookList.add(new OffNovelBook("悲惨世界",3500,"雨果"));
bookList.add(new OffNovelBook("梅",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)+"元");
}
}
}
上面的例子可以很清晰的让我们了解开闭原则定义。
持续更新中........
浅析JAVA设计模式(三)的更多相关文章
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
- 浅析JAVA设计模式之工厂模式(二)
1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...
- 浅析JAVA设计模式(一)
第一写技术博客,只是想把自己一天天积累的东西与大家分享.今天在看<大型网站架构和java中间件>这本书时,其中提到代理模式的动态代理.作为java中间件的一个重要基础,我觉的有必要整理和分 ...
- 浅析JAVA设计模式(二)
2. 里氏替换原则:LSP(Liskov Substitution Principle)里氏替换原则,定义为只要父类出现的地方子类就可以出现,而且用子类替换后,程序也不会出现问题,使用者根本不用关心是 ...
- java设计模式---三种工厂模式之间的区别
简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式.其主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性. 本文是本人对这三种模式学习后的一个小结以及对他 ...
- java设计模式三种工厂模式简单介绍
一.简单工厂模式 概述:简单工厂模式的创建意图就是,把对类的创建初始化全都交给一个工厂来执行,而用户不需要去关心创建的过程是什么样的,只用告诉工厂我想要什么就行了.而这种方法的缺点也很明显,违背了设计 ...
- 阿里架构师浅析Java设计模式之虚拟代理模式
虚拟代理模式(Virtual Proxy)是一种节省内存的技术,它建议创建那些占用大量内存或处理复杂的对象时,把创建这类对象推迟到使用它的时候.在特定的应用中,不同部分的功能由不同的对象组成,应用启动 ...
- java设计模式(三)--抽象工厂模式
转载:http://zz563143188.iteye.com/blog/1847029 前面的工厂方法模式虽然清晰,但还是感觉有些繁琐,通常使用的还是抽象工厂模式. 工厂方法模式有一个问题就是,类的 ...
- java设计模式---三种工厂模式
工厂模式提供创建对象的接口. 工厂模式分为三类:简单工厂模式(Simple Factory), 工厂方法模式(Factory Method)和抽象工厂模式(Abstract Factory).GOF在 ...
随机推荐
- 【腾讯Bugly干货分享】手游热更新方案xLua开源:Unity3D下Lua编程解决方案
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/2bY7A6ihK9IMcA0bOFyB-Q 导语 xL ...
- jsp <c:forEach> 判断第一条 或 最后一条记录
<c:forEach>标签具有以下一些属性: var:迭代参数的名称.在迭代体中可以使用的变量的名称,用来表示每一个迭代变量.类型为String. items:要进行迭代的集合.对于它所支 ...
- 建立树莓派raspberry交叉编译环境以及编译内核
最近买了一个树莓派,玩了几天,虽然已经有很多人玩了,现在玩好像有点晚了,但是他确实是个好东西,学好它,对嵌入式的整个开发流程也就会熟悉很多.虽然性能不是很强和现在的BB-BLACK比有点慢了,但是它便 ...
- 关于angular的ng-class条件判断
angular的ng-class的多条件判断是非常好用的,不需要写过多的判断去更改他相应的class, 但大家要记住,在repeat中使用ng-class多条件判断时, 错误写法:<i clas ...
- CAS认证(3):验证用户信息
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- CAS SSO对手机应用支持的一种思路
原文地址: http://architecture3.riaos.com/?p=3095368 手机和桌面应用访问CAS,我们不能直接使用CAS提供的web api.不过CAS提供了一个插件,叫CAS ...
- java.lang.ClassNotFoundException: Didn't find class "*****Activity" on path: /data/app/*******.apk
http://blog.csdn.net/lovexieyuan520/article/details/9032797/ 很多人出现了java.lang.RuntimeException: Unabl ...
- 查看MySQL数据库表的命令介绍
如果需要查看MySQL数据库中都有哪些MySQL数据库表,应该如何实现呢?下面就为您介绍查看MySQL数据库表的命令,供您参考. 进入MySQL Command line client下查看当前使用的 ...
- JSP 笔记
<%@ page contentType="text/html;charset=UTF-8"%> <!-- 字符编码为utf-8,不然会乱码.... --> ...
- Spring MVC自定义统一异常处理类,并且在控制台中输出错误日志
在使用SimpleMappingExceptionResolver实现统一异常处理后(参考Spring MVC的异常统一处理方法), 发现出现异常时,log4j无法在控制台输出错误日志.因此需要自定义 ...