led网站制作,怎么做网站公司宣传资料,曹鹏wordpress教程,急求聊城网站建设程序设计的原则1. 单一设计原则2. 接口隔离原则3. 依赖倒转4. 里氏替换原则5. 开闭原则6. 迪米特原则7. 合成复用1. 单一设计原则
每一个类只负责做自己的的功能。不能跨越到其它类。 不合理
package top.bitqian.principle.single_responsibility;/*** author echo lovely* …
程序设计的原则1. 单一设计原则2. 接口隔离原则3. 依赖倒转4. 里氏替换原则5. 开闭原则6. 迪米特原则7. 合成复用1. 单一设计原则
每一个类只负责做自己的的功能。不能跨越到其它类。 不合理
package top.bitqian.principle.single_responsibility;/*** author echo lovely* since 2021/4/10 16:45* description* p* 单一设计原则* li降低类的复杂度, 一个类只维护一项职责/li* li提高类的可读性, 可维护性/li* li降低变更引起的风险/li* li* usual, 一般遵守单一设计原则, * 只有逻辑足够简单, 才能label代码级别/label违反单一设计原则, * 如果方法足够少, 可以在方法级别保持单一职责原则。* /li* /p*/public class SingleResponsibility1 {public static void main(String[] args) {Vehicle vehicle new Vehicle();vehicle.run(火车);vehicle.run(汽车);// 飞机在陆地上不合理..vehicle.run(飞机);}/*** vehicle, there is...*/static class Vehicle {public void run(String vehicle) {System.out.println(vehicle 在陆地上跑.....);}}
} 基于类级别
package top.bitqian.principle.single_responsibility;/*** author echo lovely* date 2021/4/10 16:53* description P* 拆分, 将交通工具拆分为多个类, 每个交通工具做各自的事情* 优点如果每个大职责下, 有很多小的功能, 细节的地方, 比如轮船启动前, 要排水, 飞机要检修... 可以拆* 缺点当功能少, 只考虑到运行时, 下面的设计显得冗余。* /P*/public class SingleResponsibility2 {public static void main(String[] args) {// 分为三个类, 各司其职new RoadVehicle().run(汽车);new AirVehicle().run(飞机);new WaterVehicle().run(轮船);}static class RoadVehicle {public void run(String roadVehicle) {System.out.println(roadVehicle 在路上运行);}}static class AirVehicle {public void run(String airVehicle) {System.out.println(airVehicle 在天上运行);}}static class WaterVehicle {public void run(String waterVehicle) {System.out.println(waterVehicle 在水上运行);}}} 基于方法级别
package top.bitqian.principle.single_responsibility;/*** author echo lovely* date 2021/4/10 17:00* description* p* 方法级别 进行单一设计原则* /p*/public class SingleResponsibility3 {public static void main(String[] args) {Vehicle vehicle new Vehicle();vehicle.airRun(飞机);vehicle.roadRun(汽车);vehicle.waterRun(轮船);}static class Vehicle {public void roadRun(String name) {System.out.println(name 在陆地上run);}public void airRun(String name) {System.out.println(name 在天空上run);}public void waterRun(String name) {System.out.println(name 在水上run);}}}
2. 接口隔离原则
每一个接口只负责一件事记住接口是规范, 规定某种具体的行为。具体的一件事。
每一接口尽可能只负责一项功能。这里演示接口拆分将接口拆成多个接口。需求错误的设计
package top.bitqian.principle.segregation;/*** author echo lovely* date 2021/4/10 17:46* description* p* 接口隔离原则, 将接口拆分** 业务* A, B 实现MyInterface** C 通过 MyInterface依赖(使用)A, operation1, 2, 3三个方法* D 通过 MyInterface依赖B, 使用 operation1, 4, 5三个方法*** /p*/public class Segregation1 {public static void main(String[] args) {C c new C();// c中依赖 A中, operation1,2,3 方法c.dependency1(new A());c.dependency2(new A());c.dependency3(new A());// d依赖B operation1,4.,5 方法D d new D();d.dependencyD1(new B());d.dependencyD2(new B());d.dependencyD3(new B());/*分析 现在, C 依赖A (1.2.3), D 依赖B (1.4.5),而A中的4,5方法, B中的2,3方法显得多余..*/}/*** 定义接口, 5个方法 操作*/interface MyInterface {void operation1();void operation2();void operation3();void operation4();void operation5();}/*** A 实现 MyInterface*/static class A implements MyInterface {Overridepublic void operation1() {System.out.println(A operation1);}Overridepublic void operation2() {System.out.println(A operation2);}Overridepublic void operation3() {System.out.println(A operation3);}Overridepublic void operation4() {System.out.println(A operation4);}Overridepublic void operation5() {System.out.println(A operation5);}}/*** B 实现 MyInterface*/static class B implements MyInterface {Overridepublic void operation1() {System.out.println(B operation1);}Overridepublic void operation2() {System.out.println(B operation2);}Overridepublic void operation3() {System.out.println(B operation3);}Overridepublic void operation4() {System.out.println(B operation4);}Overridepublic void operation5() {System.out.println(B operation5);}}// C, D类 通过MyInterface 依赖 A, B/*** 依赖A类 1,2,3*/static class C {public void dependency1(MyInterface i) {i.operation1();}public void dependency2(MyInterface i) {i.operation2();}public void dependency3(MyInterface i) {i.operation3();}}/*** 依赖D 1,4,5*/static class D {public void dependencyD1(MyInterface i) {i.operation1();}public void dependencyD2(MyInterface i) {i.operation4();}public void dependencyD3(MyInterface i) {i.operation5();}}}
上面的接口只定义了一个接口MyInterface, 而这个接口中并不是子类都需要使用的
所以可以将这个接口拆分多个接口。让子类选择性的实现多个接口中的某几个。解决
package top.bitqian.principle.segregation.aprove;/*** author echo lovely* date 2021/4/10 18:30* description* p* 隔离方案2, 拆分接口* a hreftop.bitqian.principle.segregation.Segregation1pls see/a* /p* see top.bitqian.principle.segregation.Segregation1*/public class Segregation2 {public static void main(String[] args) {C c new C();c.dependency1(new A());c.dependency2(new A());c.dependency3(new A());D d new D();d.dependencyD1(new B());d.dependencyD2(new B());d.dependencyD3(new B());}/*将5个方法的接口, 拆分为3个部分, 让类来实现*/interface MyInterface1 {void operation1();}interface MyInterface2 {void operation2();void operation3();}interface MyInterface3 {void operation4();void operation5();}/*** A 实现1,2,3方法*/static class A implements MyInterface1, MyInterface2 {Overridepublic void operation1() {System.out.println(A impl operation1);}Overridepublic void operation2() {System.out.println(A impl operation2);}Overridepublic void operation3() {System.out.println(A impl operation3);}}/*** B实现了1,4,5 方法*/static class B implements MyInterface1, MyInterface3 {Overridepublic void operation1() {System.out.println(B impl operation1);}Overridepublic void operation4() {System.out.println(B impl operation4);}Overridepublic void operation5() {System.out.println(B impl operation5);}}/*** C 通过拆分的MyInterface1 MyInterface2两个接口 间接的依赖了A类*/static class C {public void dependency1(MyInterface1 i1) {i1.operation1();}public void dependency2(MyInterface2 i2) {i2.operation2();}public void dependency3(MyInterface2 i2) {i2.operation3();}}/*** D 通过拆分的 MyInterface1 MyInterface3两个接口 依赖了B*/static class D {public void dependencyD1(MyInterface1 i1) {i1.operation1();}public void dependencyD2(MyInterface3 i3) {i3.operation4();}public void dependencyD3(MyInterface3 i3) {i3.operation5();}}}
3. 依赖倒转
面向接口编程 需求描述
package top.bitqian.principle.dependency_inversion;/*** author echo lovely* date 2021/4/11 10:28* description* P* 依赖倒转原则:* 1. 面向接口编程* ul* li接口作为参数传递/li* li构造方法传递接口/li* lisetter传递接口参数/li* /ul* 2. 接口, 抽象类的细节越少越好, 细节应该交给子类* 3. 注意点* ul* li模块尽量使用抽象类 或者接口, (两者都实现), more stable/li* li变量的声明类型尽量是接口或者抽象类, 在变量的使用和实际对象之间, 存在缓冲层, 有利于程序扩展和优化./li* li继承遵循里氏替换原则/li* /ul* /P*/public class DemoInversion1 {public static void main(String[] args) {// somebody get a msg from email..// but he just got a email..new Person().receive(new Email());}static class Email {String getInfo() {return from email: hello, adorable;}}static class Person {void receive(Email email) {String msg email.getInfo();System.out.println(msg);}}} 定义接口使用接口作为依赖
package top.bitqian.principle.dependency_inversion.improve;/*** author echo lovely* date 2021/4/11 10:41* description p* 模仿person接收消息* /p*/public class DemoInversion2 {public static void main(String[] args) {/** 依赖倒转 like 多态*/Person p new Person();p.receive(new Email());p.receive(new YouTelegram());}/*** 获取消息接口*/interface IReceiver {String getInfo();}static class Email implements IReceiver {Overridepublic String getInfo() {return from email: hello, adorable;}}static class YouTelegram implements IReceiver {Overridepublic String getInfo() {return from t.me: hello, bitQian;}}/*** person 接收到消息*/static class Person {void receive(IReceiver receiver) {String info receiver.getInfo();System.out.println(info);}}}
上面的依赖是通过参数传递, 还可以通过setter方法, 构造器。
4. 里氏替换原则
继承需要遵循这个原则。
1. 如果父类是普通的类(非抽象接口) 不要改写父的方法实现。
2. 如果重载父类实现的方法, 子类的方法参数必须比父类的大
父是ArrayList子则是List或者Collection或者Iterator
3. 重载, 返回要比父的小
4. 父是abstract, 则必须实现父的抽象。子类可以有自己的方法。package top.bitqian.principle.liskov;import java.util.HashMap;
import java.util.Map;/*** author echo lovely* date 2021/4/12 20:34* description* p* 继承缺点* p* 继承是侵入性的。只要继承就必须拥有父类的所有属性和方法。* 降低了代码的灵活性。因为继承时父类会对子类有一种约束。* 增强了耦合性。当需要对父类的代码进行修改时必须考虑到对子类产生的影响。* 有时修改了一点点代码都有可能需要对打断程序进行重构。* /p* 里氏替换原则: strong只要有父类出现的地方都可以用子类来替代/strong* li* pls see a hrefhttps://www.jianshu.com/p/cf9f3c7c0df5extends../a* /li* li* case1: 子类必须实现父类的抽象方法但不得重写覆盖父类的非抽象已实现方法。* case2: 子类中可以增加自己特有的方法。* case3: 当子类覆盖或实现父类的方法时方法的前置条件即方法的形参要比父类方法的输入参数更宽松。(形参更大)* case4: 当子类的方法实现父类的抽象方法时方法的后置条件即方法的返回值要比父类更严格。(返回更小)* /li* /p*/public class Liskov1 {public static void main(String[] args) {A a new A();System.out.println(3-2 a.fun1(3, 2));System.out.println(----------);B b new B();System.out.println(3-2 b.fun1(3, 2));// 执行了父类方法, 但是hello并未被重写... 可能导致程序的混乱..Map?, ? map new HashMap();Case3.A a1 new Case3.A();a1.hello(map);// 执行了子类方法Case3.B b1 new Case3.B();b1.hello(new HashMap());// {}父类的方法b1.hello(map);}static class A {// but thats sub.. 编程时有可能写错int fun1(int a, int b) {return a - b;}}/*** 子类不可实现父类已经实现的方法*/static class B extends A {// add, 子类不要覆盖父类已经实现的方法..Overrideint fun1(int a, int b) {return a b;}}static class Case3 {static class A {void hello(Map?, ? map) {System.out.println(map 父类的方法);}}static class B extends Case3.A {// 重载了...void hello(HashMap?, ? map) {System.out.println(map 子类的方法);}}}/*** 子类的返回必须比父类小*/static class Case4 {static abstract class A {abstract Map?, ? fun1();}static class B extends Case4.A {/*** 返回值类型必须比父类的小, 否则编译器报错* return null*/HashMap?, ? fun1() {return null;}}}} 使用抽象, 抽取, 解决
package top.bitqian.principle.liskov.improve;/*** author echo lovely* date 2021/4/12 21:17* description p* 更好的解决方案* /p*/public class Liskov2 {public static void main(String[] args) {A a new A();System.out.println(3-2 a.fun1(3, 2));System.out.println(----------);B b new B();System.out.println(32 b.fun1(3, 2));System.out.println(3-2 b.fun2(3, 2));}static abstract class Base {}static class A extends Base {public int fun1(int a, int b) {return a - b;}}/*** 通过继承基类 解耦...*/static class B extends Base {// 依赖 Aprivate final A myA new A();// B与A 无关 不可能认为是重写 add..int fun1(int a, int b) {return a b;}int fun2(int a, int b) {return this.myA.fun1(a, b);}}}
5. 开闭原则 画图demo
package top.bitqian.principle.open_close;/*** author echo lovely* date 2021/4/17 10:04* description* p* ocp 开闭原则...* li提供方可扩展, 调用方关闭, 调用方不修改/li* /p*/public class Ocp {public static void main(String[] args) {new GraphicEditor(new Circle());new GraphicEditor(new Triangle());}// 调用方static class GraphicEditor {private final Shape shape;GraphicEditor(Shape shape) {this.shape shape;this.drawCircle();}void drawCircle() {// fixme: 如果我有很多形状, 这里要加很多判断if (shape.type 1) {System.out.println(draw circle...);}if (shape.type 2) {System.out.println(draw Triangle...);}}}// 提供方static class Shape {Integer type;}static class Circle extends Shape {Circle() {super.type 1;}}static class Triangle extends Shape {Triangle() {super.type 2;}}} 通过依赖抽象解决
package top.bitqian.principle.open_close.improve;/*** author echo lovely* date 2021/4/17 10:13* description* p* 开闭原则实现demo* /p*/public class Ocp1 {public static void main(String[] args) {new GraphicEditor(new Circle()).drawShape();new GraphicEditor(new Triangle()).drawShape();}// 调用方static class GraphicEditor {private final Shape shape;GraphicEditor(Shape shape) {this.shape shape;}/*** draw sth...*/void drawShape() {// 这里可以不用改变了, 只要改变子类的实现细节, 就可画出不同的形状..shape.shapeDetail();}}// 提供方static abstract class Shape {Integer type;/*** 提供抽象*/abstract void shapeDetail();}static class Circle extends Shape {Circle() {super.type 1;}Overridevoid shapeDetail() {System.out.println(draw circle...);}}static class Triangle extends Shape {Triangle() {super.type 2;}Overridevoid shapeDetail() {System.out.println(draw triangle...);}}}
6. 迪米特原则
抽取, 低耦合, 封装保持在成员变量参数返回值直接的耦合。
不要在方法体里面出现默认类。(别在方法体里面new陌生对象。)package top.bitqian.principle.demeter;import lombok.Data;import java.util.ArrayList;
import java.util.List;/*** author echo lovely* date 2021/4/17 11:27* description p* 迪米特原则:* 最小知道原则, 对依赖的类知道的越少越好, 依赖类只提供public方法给被依赖类访问* 通过方法参数, 方法返回值, 成员变量产生耦合* /p*/public class Demeter1 {public static void main(String[] args) {//创建了一个 SchoolManager 对象SchoolManager schoolManager new SchoolManager();//输出学院的员工 id 和 学校总部的员工信息schoolManager.printAllEmployee(new CollegeManager());}//学校总部员工类Datastatic class Employee {private String id;}//学院的员工类Datastatic class CollegeEmployee {private String id;}//管理学院员工的管理类static class CollegeManager {//返回学院的所有员工public ListCollegeEmployee getAllEmployee() {ListCollegeEmployee list new ArrayList();for (int i 0; i 10; i) { //这里我们增加了 10 个员工到 listCollegeEmployee emp new CollegeEmployee();emp.setId(学院员工 id i);list.add(emp);}return list;}}//学校管理类//分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager//CollegeEmployee 不是 直接朋友 而是一个陌生类这样违背了 迪米特法则static class SchoolManager {//返回学校总部的员工public ListEmployee getAllEmployee() {ListEmployee list new ArrayList();for (int i 0; i 5; i) { //这里我们增加了 5 个员工到 listEmployee emp new Employee();emp.setId(学校总部员工 id i);list.add(emp);}return list;}//该方法完成输出学校总部和学院员工信息(id)void printAllEmployee(CollegeManager sub) {//分析问题//1. 这 里 的 CollegeEmployee 不是 SchoolManager 的直接朋友//2. CollegeEmployee 是以局部变量方式出现在 SchoolManager//3. 违反了迪米特法则// fixeme: 可将下面的这段代码抽取到CollegeManager//获取到学院员工ListCollegeEmployee list1 sub.getAllEmployee();System.out.println(------------学院员工------------);for (CollegeEmployee e : list1) {System.out.println(e.getId());}//获取到学校总部员工ListEmployee list2 this.getAllEmployee();System.out.println(------------学校总部员工------------);for (Employee e : list2) {System.out.println(e.getId());}}}}
7. 合成复用
package top.bitqian.principle.composite;/** author echo lovely* date 2021/4/17 15:38* description* p* 合成复用原则: 如果两个类没有多大关系, 不要使用继承关系。* 1. 使用依赖关系, 依赖的类作为方法参数.* 2. 使用聚合关系作为成员变量, 使用构造器, 或者setter方法初始化.* 3. 使用复用关系, 初始化的成员变量.* /p*/