浅析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{
10     public void depend1(I i){
11         i.method1();
12     }
13     public void depend2(I i){
14         i.method2();
15     }
16     public void depend3(I i){
17         i.method3();
18     }
19 }
20 
21 class B implements I{
22     public void method1() {
23         System.out.println("类B实现接口I的方法1");
24     }
25     public void method2() {
26         System.out.println("类B实现接口I的方法2");
27     }
28     public void method3() {
29         System.out.println("类B实现接口I的方法3");
30     }
31     //对于类B来说,method4和method5不是必需的,但是由于接口A中有这两个方法,
32     //所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。
33     public void method4() {}
34     public void method5() {}
35 }
36 
37 class C{
38     public void depend1(I i){
39         i.method1();
40     }
41     public void depend2(I i){
42         i.method4();
43     }
44     public void depend3(I i){
45         i.method5();
46     }
47 }
48 
49 class D implements I{
50     public void method1() {
51         System.out.println("类D实现接口I的方法1");
52     }
53     //对于类D来说,method2和method3不是必需的,但是由于接口A中有这两个方法,
54     //所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。
55     public void method2() {}
56     public void method3() {}
57 
58     public void method4() {
59         System.out.println("类D实现接口I的方法4");
60     }
61     public void method5() {
62         System.out.println("类D实现接口I的方法5");
63     }
64 }
65 
66 public class Client{
67     public static void main(String[] args){
68         A a = new A();
69         a.depend1(new B());
70         a.depend2(new B());
71         a.depend3(new B());
72         
73         C c = new C();
74         c.depend1(new D());
75         c.depend2(new D());
76         c.depend3(new D());
77     }

  相信大家也看出来了接口I太过臃肿了,实际开发中我们应该尽可能的避免这种现象出现。接口定义尽量细化。针对上面的问题,我们可以采用接口隔离来进行解决接口臃肿的问题。

 改造后代码:

1 interface I1 {
 2     public void method1();
 3 }
 4 
 5 interface I2 {
 6     public void method2();
 7     public void method3();
 8 }
 9 
10 interface I3 {
11     public void method4();
12     public void method5();
13 }
14 
15 class A{
16     public void depend1(I1 i){
17         i.method1();
18     }
19     public void depend2(I2 i){
20         i.method2();
21     }
22     public void depend3(I2 i){
23         i.method3();
24     }
25 }
26 
27 class B implements I1, I2{
28     public void method1() {
29         System.out.println("类B实现接口I1的方法1");
30     }
31     public void method2() {
32         System.out.println("类B实现接口I2的方法2");
33     }
34     public void method3() {
35         System.out.println("类B实现接口I2的方法3");
36     }
37 }
38 
39 class C{
40     public void depend1(I1 i){
41         i.method1();
42     }
43     public void depend2(I3 i){
44         i.method4();
45     }
46     public void depend3(I3 i){
47         i.method5();
48     }
49 }
50 
51 class D implements I1, I3{
52     public void method1() {
53         System.out.println("类D实现接口I1的方法1");
54     }
55     public void method4() {
56         System.out.println("类D实现接口I3的方法4");
57     }
58     public void method5() {
59         System.out.println("类D实现接口I3的方法5");
60     }

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();//原价
10         
11         int offPrice=0;//打折之后的价格,初始化为0
12         if(selfPrice>4000){
13             offPrice=selfPrice * 90 / 100;
14         }
15         else{
16             offPrice=selfPrice * 80 / 100;
17         }
18         
19         return offPrice;
20     }
21 }
22 public class BookStore {
23     private final static ArrayList<IBook> bookList=new ArrayList<IBook>();
24     static{
25         bookList.add(new OffNovelBook("天龙八部",3200,"金庸"));
26         bookList.add(new OffNovelBook("巴黎圣母院",5600,"雨果"));
27         bookList.add(new OffNovelBook("悲惨世界",3500,"雨果"));
28         bookList.add(new OffNovelBook("梅",4300,"兰陵笑笑生"));
29     }
30     public static void main(String[] args) {
31         NumberFormat formatter=NumberFormat.getCurrencyInstance();
32         formatter.setMaximumFractionDigits(2);
33         System.out.println("书店卖出去的书籍记录如下:");
34         for(IBook book:bookList){
35             System.out.println("书籍名称:"+book.getName()+
36                              "\t书籍作者:"+book.getAuthor()+
37                              "\t书籍价格:"+formatter.format(book.getPrice()/100.0)+"元");
38         }
39     }
40 
41 }

上面的例子可以很清晰的让我们了解开闭原则定义。

持续更新中........ 

时间: 2025-01-02 11:25:08

浅析JAVA设计模式(三)的相关文章

浅析JAVA设计模式之工厂模式(三)

在阅读本文之前,请先阅读(一)和(二)中的简单工厂模式和工厂方法模式. 1抽象工厂模式简介 抽象工厂 (Abstract Factroy) 模式:工具箱模式(kit).抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态,如下图. 图1.1 上图左边有一个工厂类的等级结构,右边有两个不同的产品等级结构,分别是产品A的等级结构和产品B的等级结构,工厂1和工厂2分别负责不同一个产品等级,同一个产品族的产品的生产.又例如下图: 图1.2 上图表示的是Button和Text两个不同产品的等级

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

1 工厂模式简介 工厂模式的定义:简单地说,用来实例化对象,代替new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式可以动态决定将哪一个类实例化,不用先知道每次要实例化哪一个类. 工厂模式可以分一下三种形态: 简单工厂 (Simple Factory)模式:又称静态工厂模式(StaticFactory). 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory). 抽象工厂 (Abstract Factroy)模式:又称工具箱模式

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

1 工厂方法模式简介 工厂方法 (Factroy Method) 模式:又称多态性工厂模式(Polymorphic Factory),在这种模式中,核心工厂不再是一个具体的类,而是一个抽象工厂,提供具体工厂实现的接口,具体创建产品交由子工厂去做,抽象工厂不涉及任何产品被实例化的细节.而不同等级的产品,就对应一个不同等级的工厂,如下图. 图1 1.1工厂方法模式(多态性工厂模式): 工厂方法模式有三个角色: 1. 抽象产品接口 2. 具体产品类 3. 抽象工厂接口 4.具体工厂类. 1.2工厂方法

浅析JAVA设计模式(一)

第一写技术博客,只是想把自己一天天积累的东西与大家分享.今天在看<大型网站架构和java中间件>这本书时,其中提到代理模式的动态代理.作为java中间件的一个重要基础,我觉的有必要整理和分析下java的23种设计模式,如有不对的地方,请大家留贴指正. 一.设计模式的分类 总体来说,Java的设计模式分为三个大类(创建型模式.结构型模式.行为型模式) 创建型模式:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式:适配器模式.装饰模式.代理模式.外观模式(又称门面模式).桥

浅析JAVA设计模式(二)

2. 里氏替换原则:LSP(Liskov Substitution Principle)里氏替换原则,定义为只要父类出现的地方子类就可以出现,而且用子类替换后,程序也不会出现问题,使用者根本不用关心是父类还是子类.这也是我们java继承特性的一个表现. 下面用个实际项目中遇到的一个简单的需求:现在有A类产品需要调用method1(),B类产品也需要调用method(),同样C类产品也需要调用method(),但是我们需要直接让D这个人去处理这个Method(),那么我们可以这样设计一个抽象类Ab

浅析JAVA设计模式之单例模式(一)

1 单例模式简介 单例模式确保一个类只有一个实例,并且自行实行实例化并向整个系统提供这个实例. 单例模式有三个要点: 1.某个类只能有一个实例. 2.它必须自行创建这个实例. 3.它必须向整个系统提供这个实例. 单例模式主要分为两种:饿汉式单例模式和懒汉式单例模式 1.1饿汉式单例模式: 饿汉式单例模式是java语言实现起来最为简单的单例模式,UML图如下: 图1.1 从图中可以看出,它自己将自己实例化. 1.2饿汉式单例模式的实现(建一个Singleton包,所有程序放在该包下): (1)建一

浅析Java设计模式 - 单例模式

以下是三种单例模式的代码实现,前两者用的比较多 (言外之意 最后一种可以忽略) 1 package com.signle; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 /** 7 * 8 * @title 单例模式 9 * @Copyright Copyright (c)2016年3月9日 10 * @Company CTC 11 * @version 1.0 12 * @author ejokovic 13 * @time

Java设计模式(三) 之 适配器模式

源码均以JDK1.8作为参考 1.定义: 将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 2.解析: Adapter Pattern又称为Wrapper Pattern,提到Adapter Pattern,最先会想到的可能就是电源适配器,例如一台12V的电脑需要改到家用220V交流电源上使用,就需要使用交流电适配器,对电源进行转换. 在Java语言中,就是为了将现有类进行包装或适配来完成既有功能. 通用类图: 类图解析: 2.1.Cl

Java设计模式(三) Visitor(訪问者)模式及多分派场景应用

基本概念 Visitor 封装一些作用于数据结构中的各元素的操作,不同的操作能够借助新的visitor实现.减少了操作间的耦合性 訪问者能够将数据结构和对数据的操作解耦,使得添加对数据结构的操作不须要取改动数据结构,也不必去改动原有的操作,而运行时再定义新的Visitor时闲着即可了(在操作加入上易拓展) 模式中角色分工 Visitor:抽象訪问者,在重载的visit函数中声明訪问者能够訪问的对象. Concrete Visitor:实现一个訪问者对于一个详细的元素的操作 Element:抽象元