浅谈设计模式的六大原则

xiaoxiao2021-02-28  33

转发请注明出处:http://blog.csdn.net/qq_28055429/article/details/51507170

一,单一职责原则:就一个类而言,应该仅有一个引起它变化的原因(就是实现类要责任单一)

英文–Single Responsibility Principle 

简写:SRP

举个例子:

   父类:Animal

[java] view plain copy print ? public class Animal {             void move(String animal){          System.out.println(animal + ”是主要用脚来移动的”);      }  }   public class Animal { void move(String animal){ System.out.println(animal + "是主要用脚来移动的"); } } [java] view plain copy print ? 测试类:   测试类: [java] view plain copy print ?  <pre name=“code” class=“java”>public class SRPTest {    public static void main(String[] args) {      Animal animal = new Animal();      animal.move(”狗”);      animal.move(”猫”);      animal.move(”老鼠”);    }   <pre name="code" class="java">public class SRPTest { public static void main(String[] args) { Animal animal = new Animal(); animal.move("狗"); animal.move("猫"); animal.move("老鼠"); } }

输出:

[java] view plain copy print ? 狗是主要用脚来移动的  猫是主要用脚来移动的  老鼠是主要用脚来移动的   狗是主要用脚来移动的 猫是主要用脚来移动的 老鼠是主要用脚来移动的那么问题来了,当你添加鸟时,打印出,鸟主要是用脚来移动的,(但好像是翅膀,这里假设为翅膀)

这时,需要改代码了:

如果这样改:

[java] view plain copy print ? public class Animal {             void move(String animal){          if(“鸟”.equals(animal)){              System.out.println(animal + ”是主要靠翅膀来移动的”);          }          else{              System.out.println(animal + ”是主要用脚来移动的”);          }      }  }   public class Animal { void move(String animal){ if("鸟".equals(animal)){ System.out.println(animal + "是主要靠翅膀来移动的"); } else{ System.out.println(animal + "是主要用脚来移动的"); } } }没错,可以真确输出,但违背了单一职责原则,假如又要分为类似于猫头鹰等主要靠翅膀在夜间移动的鸟,和靠翅膀在白天移动的鸟, 又该如何呢,,,再分呢?

这个时候就要考虑单一职责原则了:

第一种:好像有点违背,但在方法上又好像不违背:

[java] view plain copy print ? public class Animal {             void move(String animal){              System.out.println(animal + ”是主要靠翅膀来移动的”);          }      void moveN(String animal){              System.out.println(animal + ”是主要用翅膀来移动的”);          }        }   public class Animal { void move(String animal){ System.out.println(animal + "是主要靠翅膀来移动的"); } void moveN(String animal){ System.out.println(animal + "是主要用翅膀来移动的"); } }

第二种:

用两个类,即一个类管理一个原则:

[java] view plain copy print ? public class Animal {             void move(String animal){              System.out.println(animal + ”是主要靠翅膀来移动的”);          }    }   public class Animal { void move(String animal){ System.out.println(animal + "是主要靠翅膀来移动的"); } } [java] view plain copy print ? public class Birds {      void move(String animal) {          System.out.println(animal + ”是主要靠翅膀来移动的”);      }  }   public class Birds { void move(String animal) { System.out.println(animal + "是主要靠翅膀来移动的"); } } 测试类:

[java] view plain copy print ? public class SRPTest {        public static void main(String[] args) {          Animal animal = new Animal();          animal.move(”狗”);          animal.move(”猫”);          animal.move(”老鼠”);          Birds birds = new Birds();          birds.move(”鸟”);        }    }   public class SRPTest { public static void main(String[] args) { Animal animal = new Animal(); animal.move("狗"); animal.move("猫"); animal.move("老鼠"); Birds birds = new Birds(); birds.move("鸟"); } } 二,开放封闭原则:对扩展—开发 , 对更改—-封闭

英文:OpenClosePrinciple

简写:OCP

就是说:不要更改源代码(现有代码),而应该增加一个新的类(如子类等)

如版本更新等

版本更新:尽量不更改源代码,可以增加新功能

员工迟到问题:可以制定迟到的晚下班,迟到多久就得加班多久等制度

即:上班总时长封闭,对于迟到一点开放

三,里氏代换原则:子代父,程序行为不变化(有点类似于继承)

英文:Liskov Substitution Principle 

简写:LSP

理解:子类必须能够替换他们的父类型,使得父类模块在不改变的情况下,自己可以用扩展性

如  动物,

子:狗,猫,牛

又如一个四则运算的例子:

求加法:

[java] view plain copy print ? package testtwo;    public class Console {      int addNumber(int a , int b){          return (a + b);      }  }   package testtwo; public class Console { int addNumber(int a , int b){ return (a + b); } } 测试类:

[java] view plain copy print ? package testtwo;    public class Test {        public static void main(String[] args) {          Console console = new Console();          int result = console.addNumber(82);          System.out.println(”结果是: ” + result);      }  }   package testtwo; public class Test { public static void main(String[] args) { Console console = new Console(); int result = console.addNumber(8, 2); System.out.println("结果是: " + result); } } 输出结果:

结果是: 10

假如要先求加法再乘法呢,如 (8 + 2)* 4

那么你可能说我直接在Console更改就行啦,但万一,你有好多个类使用了Console的例子呢,那么容易出错,

于是可以新建类来继承,Console不变,

如代码:

[java] view plain copy print ? package testtwo;    public class AConsonle extends Console{      int addNumber(int a , int b){          return (a + b);      }      int mulNumber(int a , int b){          return (a * b);      }  }   package testtwo; public class AConsonle extends Console{ int addNumber(int a , int b){ return (a + b); } int mulNumber(int a , int b){ return (a * b); } } 测试类:

[java] view plain copy print ? package testtwo;    public class Test {        public static void main(String[] args) {            AConsonle aConsole = new AConsonle();          int c = aConsole.addNumber(82);          int result = aConsole.mulNumber(c, 4);          System.out.println(”输出结果是:” + result);                }  }   package testtwo; public class Test { public static void main(String[] args) { AConsonle aConsole = new AConsonle(); int c = aConsole.addNumber(8, 2); int result = aConsole.mulNumber(c, 4); System.out.println("输出结果是:" + result); } } 输出:

输出结果是:40

四:依赖倒转(置)原则:  

英文:Dependence Inversion Principle,

简称 DIP

理解:

(1)抽象不应该依赖细节,细节应该依赖于抽象

    (针对接口编程,不要针对现实编程)

(2)高层模块不应该依赖底层模块,两个都应该依赖抽象

抽象:指接口或者抽象类

例子1:假如高层要访问数据库,这时,习惯性的我们喜欢写一个类来实现访问数据库的操作(低层),

即   高层——-底层——–》数据库

但这时,突然客户要求可以根据自己爱好选择不同的存储方式呢,又该如何呢?

例子2:通过代码例子,

[java] view plain copy print ? package threetest;    public class Dog  {      public void eat(){          System.out.println(”狗正在吃饭!”);      }    }   package threetest; public class Dog { public void eat(){ System.out.println("狗正在吃饭!"); } } 动物类:

[java] view plain copy print ? public class Animal {      public void animal (Dog dog){          dog.eat();      }  }   public class Animal { public void animal (Dog dog){ dog.eat(); } }测试类:

[java] view plain copy print ? <pre name=“code” class=“java”>package threetest;    public class Test {      public static void main(String[] args){          Animal a = new Animal();          Dog dog = new Dog();          a.animal(dog);          a.animal(dog);          a.animal(dog);            }  }   <pre name="code" class="java">package threetest; public class Test { public static void main(String[] args){ Animal a = new Animal(); Dog dog = new Dog(); a.animal(dog); a.animal(dog); a.animal(dog); } }

输出结果:

狗正在吃饭!狗正在吃饭!狗正在吃饭!

那么这个时候,突然想在测试类,再增加猫正在吃饭,该如何改呢?(增加老鼠呢、、、?)

那么就该想到,依赖抽象,这里以接口为例:

代码:

接口类Ieat:

[java] view plain copy print ? package threetest;    public interface Ieat {      public void eat();  }   package threetest; public interface Ieat { public void eat(); }

狗类:

[java] view plain copy print ? package threetest;    public class Dog  implements Ieat{      public void eat(){          System.out.println(”狗正在吃饭!”);      }    }   package threetest; public class Dog implements Ieat{ public void eat(){ System.out.println("狗正在吃饭!"); } } 猫类:

[java] view plain copy print ? package threetest;    public class Cat implements Ieat{      public void eat(){          System.out.println(”猫正在吃饭!”);      }  }   package threetest; public class Cat implements Ieat{ public void eat(){ System.out.println("猫正在吃饭!"); } } 高层类:

[java] view plain copy print ? package threetest;    public class Animal {      public void animal(Ieat ieat){          ieat.eat();      }  }   package threetest; public class Animal { public void animal(Ieat ieat){ ieat.eat(); } } 测试类:

[java] view plain copy print ? package threetest;    public class Test {      public static void main(String[] args){          Animal a = new Animal();          Dog dog = new Dog();          Cat cat = new Cat();          a.animal(dog);          a.animal(dog);          a.animal(dog);          a.animal(cat);          a.animal(cat);          a.animal(cat);      }  }   package threetest; public class Test { public static void main(String[] args){ Animal a = new Animal(); Dog dog = new Dog(); Cat cat = new Cat(); a.animal(dog); a.animal(dog); a.animal(dog); a.animal(cat); a.animal(cat); a.animal(cat); } } 输出结果:

[java] view plain copy print ? 狗正在吃饭!  狗正在吃饭!  狗正在吃饭!  猫正在吃饭!  猫正在吃饭!  猫正在吃饭!   狗正在吃饭! 狗正在吃饭! 狗正在吃饭! 猫正在吃饭! 猫正在吃饭! 猫正在吃饭! 由此可见:高层类Animal依赖于抽象(这里是接口)

              底层类 :Cat , Dog 也依赖于抽象(这里是接口)

五,迪米特法则:降低类之间的耦合

英文(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP)

根本思想:是强调了类之间的松耦合,

…..类对自己依赖的类知道的越少越好

 ……与直接朋友交流

直接朋友包括:

1)当前对象本身(this) 2)以参量形式传入到当前对象方法中的对象 3)当前对象的实例变量直接引用的对象 4)当前对象的实例变量如果是一个聚集,那么聚集中的元素也都是朋友 5)当前对象所创建的对象 任何一个对象,如果满足上面的条件之一,就是当前对象的”朋友”;否则就是”陌生人”。

也可以说:

出现在成员变量、方法的输入输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于朋友类。

例子:

Animal类:Dog类属于直接朋友类,因为它是通过方法的输入输出参数成为朋友的,当Foot在方法体count内,不属于直接朋友

方法属于类的行为,一个类竟然不知道他的行为与其他类有依赖关系,这就违反了迪米特法则。

[java] view plain copy print ? package fourtest;    import java.util.ArrayList;  import java.util.List;    public class Animal {      public void count(Dog dog) {          List<Foot> list = new ArrayList<Foot>();          for(int i = 0 ; i < 10 ; i++){              list.add(new Foot());          }          dog.countFoot(list);                }  }   package fourtest; import java.util.ArrayList; import java.util.List; public class Animal { public void count(Dog dog) { List<Foot> list = new ArrayList<Foot>(); for(int i = 0 ; i < 10 ; i++){ list.add(new Foot()); } dog.countFoot(list); } } [java] view plain copy print ? </pre><pre name=“code” class=“java”>Dog类:   </pre><pre name="code" class="java">Dog类: [java] view plain copy print ? </pre><pre name=“code” class=“java”><pre name=“code” class=“java”>package fourtest;  import java.util.List;  public class Dog {      void countFoot(List list){          System.out.println(”脚共有 :” + list.size() + “只”);      }  }   </pre><pre name="code" class="java"><pre name="code" class="java">package fourtest; import java.util.List; public class Dog { void countFoot(List list){ System.out.println("脚共有 :" + list.size() + "只"); } }

Foot类:这里不写代码

[java] view plain copy print ? package fourtest;  public class Foot {    }   package fourtest; public class Foot { } 测试类:

[java] view plain copy print ? package fourtest;  public class Test {      public static void main(String[] args){          Animal al = new Animal();          Dog dog = new Dog();          al.count(dog);      }  }   package fourtest; public class Test { public static void main(String[] args){ Animal al = new Animal(); Dog dog = new Dog(); al.count(dog); } } 输出:

[java] view plain copy print ? 脚共有 :10只   脚共有 :10只没错,结果没错,但却违背了迪米特法则。

应该改为:

Animal类:

[java] view plain copy print ? package fourtest;  import java.util.ArrayList;  import java.util.List;  public class Animal {      public void count(Dog dog) {          dog.countFoot();                }  }   package fourtest; import java.util.ArrayList; import java.util.List; public class Animal { public void count(Dog dog) { dog.countFoot(); } }

Dog类: [java] view plain copy print ? package fourtest;  import java.util.ArrayList;  import java.util.List;  public class Dog {      public List<Foot> list ;      public Dog(List<Foot> footList){          this.list = footList;      }      void countFoot(){          System.out.println(”脚共有 :” + list.size() + “只”);      }     }   package fourtest; import java.util.ArrayList; import java.util.List; public class Dog { public List<Foot> list ; public Dog(List<Foot> footList){ this.list = footList; } void countFoot(){ System.out.println("脚共有 :" + list.size() + "只"); } } Foot类不变,还是没代码:

Test类:

[java] view plain copy print ? package fourtest;  import java.util.ArrayList;  import java.util.List;    public class Test {      public static void main(String[] args){          List<Foot> list = new ArrayList<Foot>();    //创建一个List表,类型为Foot          for(int i = 0 ; i < 10 ; i++){               //存放数据              list.add(new Foot());          }          Dog dog = new Dog(list);                //创建Dog对象,list作为参数          Animal al = new Animal();           //创建Animal对象          al.count(dog);                      //调用Animal对象的count方法,dog作为对象                }  }   package fourtest; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args){ List<Foot> list = new ArrayList<Foot>(); //创建一个List表,类型为Foot for(int i = 0 ; i < 10 ; i++){ //存放数据 list.add(new Foot()); } Dog dog = new Dog(list); //创建Dog对象,list作为参数 Animal al = new Animal(); //创建Animal对象 al.count(dog); //调用Animal对象的count方法,dog作为对象 } }输出:

[java] view plain copy print ? 脚共有 :10只   脚共有 :10只

又如图片:

发现每个控件都与其他控件有关系,这样如若修改一个控件,则可能会带动其他控件,

如若用迪米特法则则可以改为:增加一个中介(中间类)来管理,如下:

六,接口隔离原则:

英文:Interface Segregation Principle

简写:ISP

客户端不应该依赖它不需要的接口,一个类对一个类的依赖应该建立在最小的接口上

注意:    (1)接口尽量小,但是要有限度。

   (2)为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。    (3)提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。

举个例子:

Animal接口:

[java] view plain copy print ? package fivetest;  interface Animal {      public void eat();      public void move();      public void sleep();      public void relax();  }   package fivetest; interface Animal { public void eat(); public void move(); public void sleep(); public void relax(); }类Dog:

[java] view plain copy print ? package fivetest;  public class Dog implements Animal{      //不是abstract,需重写      //我们重写前面三个方法      public void eat() {          System.out.println(”狗正在吃饭”);      }      public void move() {          System.out.println(”狗正在移动”);      }      public void sleep() {          System.out.println(”狗正在睡觉”);          }      public void relax() {}  }   package fivetest; public class Dog implements Animal{ //不是abstract,需重写 //我们重写前面三个方法 public void eat() { System.out.println("狗正在吃饭"); } public void move() { System.out.println("狗正在移动"); } public void sleep() { System.out.println("狗正在睡觉"); } public void relax() {} } Cat类:

[java] view plain copy print ? package fivetest;  public class Cat implements Animal{      public void eat() {}      //这里重写后三个方法      public void move() {          System.out.println(”猫正在移动”);          }      public void sleep() {          System.out.println(”猫正在睡觉”);              }      public void relax() {          System.out.println(”猫正在休息”);          }  }   package fivetest; public class Cat implements Animal{ public void eat() {} //这里重写后三个方法 public void move() { System.out.println("猫正在移动"); } public void sleep() { System.out.println("猫正在睡觉"); } public void relax() { System.out.println("猫正在休息"); } } Danimal类:

[java] view plain copy print ? package fivetest;    public class Danimal {      public void a1(Animal animal){          animal.eat();      }      public void a2(Animal animal){          animal.move();      }      public void a3(Animal animal){          animal.sleep();      }  }   package fivetest; public class Danimal { public void a1(Animal animal){ animal.eat(); } public void a2(Animal animal){ animal.move(); } public void a3(Animal animal){ animal.sleep(); } } Canimal类:

[java] view plain copy print ? package fivetest;     class Canimal {      public void b2(Animal animal){          animal.move();      }      public void b3(Animal animal){          animal.sleep();      }      public void b4(Animal animal){          animal.relax();      }  }   package fivetest; class Canimal { public void b2(Animal animal){ animal.move(); } public void b3(Animal animal){ animal.sleep(); } public void b4(Animal animal){ animal.relax(); } }测试类:Test

[java] view plain copy print ? package fivetest;    public class Test {      public static void main(String[] args){            Canimal c = new Canimal();          Cat cat   = new Cat();          c.b2(cat);          c.b3(cat);          c.b4(cat);                    Danimal d = new Danimal();          Dog   dog = new Dog();          d.a1(dog);          d.a2(dog);          d.a3(dog);      }     }   package fivetest; public class Test { public static void main(String[] args){ Canimal c = new Canimal(); Cat cat = new Cat(); c.b2(cat); c.b3(cat); c.b4(cat); Danimal d = new Danimal(); Dog dog = new Dog(); d.a1(dog); d.a2(dog); d.a3(dog); } }输出结果:

[java] view plain copy print ? 猫正在移动  猫正在睡觉  猫正在休息  狗正在吃饭  狗正在移动  狗正在睡觉   猫正在移动 猫正在睡觉 猫正在休息 狗正在吃饭 狗正在移动 狗正在睡觉利用迪米特法则改后代码为:

接口:4个:

[java] view plain copy print ? public interface Eat {      public void eat();  }    public interface Move {      public void move();  }    public interface Sleep {      public void sleep();  }    public interface Relax {      public void relax();  }   public interface Eat { public void eat(); } public interface Move { public void move(); } public interface Sleep { public void sleep(); } public interface Relax { public void relax(); }

Dog类:

[java] view plain copy print ? public class Dog implements Eat , Move , Sleep{      //我们重写前面三个方法      public void eat() {          System.out.println(”狗正在吃饭”);      }      public void move() {          System.out.println(”狗正在移动”);      }      public void sleep() {          System.out.println(”狗正在睡觉”);          }  }   public class Dog implements Eat , Move , Sleep{ //我们重写前面三个方法 public void eat() { System.out.println("狗正在吃饭"); } public void move() { System.out.println("狗正在移动"); } public void sleep() { System.out.println("狗正在睡觉"); } } Cat类:

[java] view plain copy print ? public class Cat implements Move , Sleep , Relax{      //这里重写后三个方法      public void move() {          System.out.println(”猫正在移动”);          }      public void sleep() {          System.out.println(”猫正在睡觉”);              }      public void relax() {          System.out.println(”猫正在休息”);          }  }   public class Cat implements Move , Sleep , Relax{ //这里重写后三个方法 public void move() { System.out.println("猫正在移动"); } public void sleep() { System.out.println("猫正在睡觉"); } public void relax() { System.out.println("猫正在休息"); } }Danimal类:

[java] view plain copy print ? public class Danimal {      public void a1(Eat e){          e.eat();      }      public void a2(Move m){          m.move();      }      public void a3(Sleep s){          s.sleep();      }  }   public class Danimal { public void a1(Eat e){ e.eat(); } public void a2(Move m){ m.move(); } public void a3(Sleep s){ s.sleep(); } } Canimal类:

[java] view plain copy print ?  class Canimal {      public void b2(Move m){          m.move();      }      public void b3(Sleep s){          s.sleep();      }      public void b4(Relax r){          r.relax();      }  }   class Canimal { public void b2(Move m){ m.move(); } public void b3(Sleep s){ s.sleep(); } public void b4(Relax r){ r.relax(); } } 测试类: [java] view plain copy print ? public class Test {      public static void main(String[] args){            Canimal c = new Canimal();          Cat cat   = new Cat();          c.b2(cat);          c.b3(cat);          c.b4(cat);                    Danimal d = new Danimal();          Dog   dog = new Dog();          d.a1(dog);          d.a2(dog);          d.a3(dog);      }     }   public class Test { public static void main(String[] args){ Canimal c = new Canimal(); Cat cat = new Cat(); c.b2(cat); c.b3(cat); c.b4(cat); Danimal d = new Danimal(); Dog dog = new Dog(); d.a1(dog); d.a2(dog); d.a3(dog); } } 输出结果: [java] view plain copy print ? 猫正在移动  猫正在睡觉  猫正在休息  狗正在吃饭  狗正在移动  狗正在睡觉   猫正在移动 猫正在睡觉 猫正在休息 狗正在吃饭 狗正在移动 狗正在睡觉

</div>
转载请注明原文地址: https://www.6miu.com/read-2628673.html

最新回复(0)