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设计模式(三)的更多相关文章

  1. 浅析JAVA设计模式之工厂模式(一)

    1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...

  2. 浅析JAVA设计模式之工厂模式(二)

    1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...

  3. 浅析JAVA设计模式(一)

    第一写技术博客,只是想把自己一天天积累的东西与大家分享.今天在看<大型网站架构和java中间件>这本书时,其中提到代理模式的动态代理.作为java中间件的一个重要基础,我觉的有必要整理和分 ...

  4. 浅析JAVA设计模式(二)

    2. 里氏替换原则:LSP(Liskov Substitution Principle)里氏替换原则,定义为只要父类出现的地方子类就可以出现,而且用子类替换后,程序也不会出现问题,使用者根本不用关心是 ...

  5. java设计模式---三种工厂模式之间的区别

    简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式.其主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性. 本文是本人对这三种模式学习后的一个小结以及对他 ...

  6. java设计模式三种工厂模式简单介绍

    一.简单工厂模式 概述:简单工厂模式的创建意图就是,把对类的创建初始化全都交给一个工厂来执行,而用户不需要去关心创建的过程是什么样的,只用告诉工厂我想要什么就行了.而这种方法的缺点也很明显,违背了设计 ...

  7. 阿里架构师浅析Java设计模式之虚拟代理模式

    虚拟代理模式(Virtual Proxy)是一种节省内存的技术,它建议创建那些占用大量内存或处理复杂的对象时,把创建这类对象推迟到使用它的时候.在特定的应用中,不同部分的功能由不同的对象组成,应用启动 ...

  8. java设计模式(三)--抽象工厂模式

    转载:http://zz563143188.iteye.com/blog/1847029 前面的工厂方法模式虽然清晰,但还是感觉有些繁琐,通常使用的还是抽象工厂模式. 工厂方法模式有一个问题就是,类的 ...

  9. java设计模式---三种工厂模式

    工厂模式提供创建对象的接口. 工厂模式分为三类:简单工厂模式(Simple Factory), 工厂方法模式(Factory Method)和抽象工厂模式(Abstract Factory).GOF在 ...

随机推荐

  1. 解决高版本 Google Chrome 扩展程序强制停用问题 -摘自网络

    1]前往这里下载你喜欢的语言的组策略模板 后缀为.adm (其他的文件自己看 https://docs.google.com/viewer?a=v&pid=sites&srcid=Y2 ...

  2. 高性能以太网芯片W5500 数据手册 V1.0(二)

    继续给大家介绍W5500 数据手册. 2.4       固定数据长度模式(FDM) 在外设主机不能控制 SCSn 时,可以使用固定数据长度模式. 此时,SCSn 必须连接到低电平(保持接地).与此同 ...

  3. 开发日志_Jan.8.2017

    这两天继续着手开发碰撞部分. 主要工作是写碰撞类和运动线程类.碰撞主要在于算法,运动线程只要管理好就行了. 之前碰撞测试中(即还未添加完整碰撞算法时)遇到各种bug,疑似机器人和小球的定位点不明所造成 ...

  4. 【腾讯优测干货分享】如何降低App的待机内存(五)——优化dex相关内存及本章总结

    本文来自于腾讯优测公众号(wxutest),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/01Abwe0p1h3WLh28Tzg_Dw 1.5案例:优化dex相 ...

  5. Effective Java:Ch4_Class:Item13_最小化类及其成员的可访问性

    要区别一个模块是否设计良好,最重要的因素是,对于其他模块而言该模块隐藏其内部数据和其他实现细节的程度.设计良好的模块应该隐藏所有实现细节,将API与其实现清晰地隔离开来.这样,模块之间通过他们的API ...

  6. C++ 实现按随意键继续~~~

    近期让学生敲代码交作业的时候要求他们仅仅给我交个cpp文件和一个exe文件,这样交上来的东西不至于太多,不占我的地方,可是有一个问题是exe它总是执行完后就直接关闭界面了,看不到执行结果的界面. 然后 ...

  7. Android UI开发第三十三篇——Navigation Drawer For Android API 7

    Creating a Navigation Drawer中使用的Navigation Drawer的android:minSdkVersion="14",现在Android API ...

  8. Citrix服务器虚拟化之三十 XenApp 6.5发布流式应用程序

                                        Citrix服务器虚拟化之三十 XenApp 6.5发布流式应用程序   XenApp可发布以下类型的资源向用户提供信息访问,这 ...

  9. C# - 系统类 - Math类

    Math类 ns:System 此类除了提供了最基本的运算功能 还提供了三角.指数.超常的计算 它的所有方法都是静态的 Math类的字段 E 常量e 自然对数底 值为2.71828182845905 ...

  10. 在windows C++中编译并使用Lua脚本

    早前就用过LUA ,只是局部的小项目使用,突然兴起想要写一些关于LUA 的  文章,记录曾经学习过的点点滴滴. 这里我使用的是LUA5.2作为 案例 lua做为轻量级脚本语言已经被广泛应用到应用软件以 ...