浅析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 }    

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

 

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

你可能感兴趣的:(java设计模式)