设计模式体现了代码的耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性。
即一个类应该只负责一项职责。
- package com.taoke.designPattern.principle;
-
- /**
- * 单一职责原则
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class SingleResponsibility {
-
- public static void main(String[] args) {
- Vehicle vehicle = new Vehicle();
- vehicle.run("飞机");
- vehicle.run("摩托车");
- vehicle.run("汽车");
- }
-
- }
-
- /**
- * 交通工具中的run方法中违反 单一职责原则
- * 应该将交通方式的不同,分解成不同的类
- *
- * @author taoke
- * @date 2022/7/29
- */
- class Vehicle {
- public void run(String string) {
- System.out.println(string + "在公路上运行。。。");
- }
- }
客户端不应该依赖它不需要的接口,即对一个类的依赖应该建立在最小的接口上
类A通过Interface会依赖类B,但是类A只会使用到接口的1,2,3方法;类C通过Interface会依赖类B,但是类C只会使用到接口的4,5方法;那么接口Interface对于类A和类C来说不是最小接口
根据接口隔离原则,应该将接口Interface拆分为多个接口,类A和类C应该与他们需要的接口产生联系
- package com.taoke.designPattern.principle;
-
- /**
- * 接口隔离原则
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class InterfaceSegregation {
-
- interface Interface1 {
- void operate1();
- void operate2();
- void operate3();
- }
-
- interface Interface2 {
- void operate4();
- void operate5();
- }
-
- class A implements Interface1 {
- @Override
- public void operate1() {}
-
- @Override
- public void operate2() {}
-
- @Override
- public void operate3() {}
- }
-
- class C implements Interface2 {
-
- @Override
- public void operate4() {}
-
- @Override
- public void operate5() {}
- }
-
- class B implements Interface1, Interface2 {
-
- @Override
- public void operate1() {}
-
- @Override
- public void operate2() {}
-
- @Override
- public void operate3() {}
-
- @Override
- public void operate4() {}
-
- @Override
- public void operate5() {}
- }
- }
高层模块不应该依赖低层模块,二者都应该依赖其抽象(缓冲层)
抽象不应该依赖细节,细节应该依赖抽象
依赖倒转(倒置)的中心思想是面向接口编程
依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中, 抽象指的是接口或抽象类,细节就是具体的实现类
使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成
- package com.taoke.designPattern.principle;
-
- /**
- * 依赖倒转原则
- * 实现Person接收不同类型消息的功能,引入一个抽象的接口IReceive,表示接收者
- * 这样Person类与接口IReceive发生依赖
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class DependenceInversion {
-
- public static void main(String[] args) {
- Person person = new Person();
- person.receive(new Email());
- person.receive(new Wechat());
- }
- }
-
- interface IReceive {
- String getInfo();
- }
-
- class Person {
- public void receive(IReceive receive) {
- System.out.println(receive.getInfo());
- }
- }
-
- class Email implements IReceive {
-
- @Override
- public String getInfo() {
- return "电子邮件信息";
- }
- }
-
- class Wechat implements IReceive {
-
- @Override
- public String getInfo() {
- return "微信信息";
- }
- }
里氏替换原则(Liskov Substitution Principle)在1988年,由麻省理工学院一位姓里的女士提出
如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象
在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
继承实际上让两个类耦合性增强了,给程序带来侵入性。在适当的情况下,
可以通过聚合,组合,依赖来解决问题
继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏
- package com.taoke.designPattern.principle;
-
- /**
- * 里氏替换原则
- * A类没有重写父类的方法,B类重写了父类的方法
- * A类继承父类,使用父类的方法,B类继承父类,并重写了父类的方法,造成错误
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class LiskovSubstitution {
- public static void main(String[] args) {
- A a = new A();
- System.out.println("2-1=" + a.func1(2, 1));
-
- B b = new B();
- System.out.println("2-1=" + b.func1(2, 1));
- }
- }
-
- class Base {
- /**
- * 父类定义了一个基础方法
- *
- * @param num1 数值1
- * @param num2 数值2
- * @return 值
- */
- public int func1(int num1, int num2) {
- return num1 - num2;
- }
- }
-
- class A extends Base {
- }
-
- class B extends Base {
- /**
- * 重写了父类方法,造成原有方法发生改变。
- *
- * @param num1 数值1
- * @param num2 数值2
- * @return 值
- */
- @Override
- public int func1(int num1, int num2) {
- return num1 + num2;
- }
- }
- package com.taoke.designPattern.principle;
-
- /**
- * 开闭原则
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class OpenClosed {
- public static void main(String[] args) {
- Use use = new Use();
- use.drawShape(new Triangle());
- use.drawShape(new Circle());
- //只需要让 此类继承 抽象类,子类实现具体方法 OCP原则
- use.drawShape(new OtherGraphics());
- }
- }
-
- class Use {
- public void drawShape(Shape shape) {
- shape.draw();
- }
- }
-
- abstract class Shape {
- public abstract void draw();
- }
-
- class Triangle extends Shape {
-
- @Override
- public void draw() {
- System.out.println("子类实现具体功能:三角形");
- }
- }
-
- class Circle extends Shape {
-
- @Override
- public void draw() {
- System.out.println("子类实现具体功能:圆形");
- }
- }
-
- class OtherGraphics extends Shape {
-
- @Override
- public void draw() {
- System.out.println("子类实现具体功能:任何形状");
- }
- }
- class A{
- B b;//全局变量 - 直接朋友
- public B m1(){} //方法返回值 - 直接朋友
- public void m2(B b){}//方法入参 - 直接朋友
- public void m3(){
- B b1 = new B();// 局部变量 非直接朋友
- }
- }
- package com.taoke.principle;
-
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * 迪米特法则
- * 学校管理类应该最少知道学院员工的信息
- * printAllEmployee 方法中,只提供方法,不把具体实现放在其他类里面。
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class Demeter {
- public static void main(String[] args) {
- SchoolManager schoolManager = new SchoolManager();
- schoolManager.printAllEmployee(new CollegeManager());
- }
- }
-
- /**
- * 学院员工类
- */
- class CollegeEmployee {
- private String id;
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
- }
-
- /**
- * 管理学院员工的管理类
- */
- class CollegeManager {
- //返回学院的所有员工
- public List
getAllEmployee() { - List
list = new ArrayList<>(); - //这里我们增加了10 个员工到list ,
- for (int i = 0; i < 10; i++) {
- CollegeEmployee emp = new CollegeEmployee();
- emp.setId("学院员工id " + i);
- list.add(emp);
- }
- return list;
- }
-
- /**
- * 打印学院所有的员工
- */
- public void printCollegeEmployee() {
- List
list = this.getAllEmployee(); - System.out.println("---学院员工----");
- for (CollegeEmployee e : list) {
- System.out.println(e.getId());
- }
- }
- }
-
- /**
- * 学校员工类
- */
- class SchoolEmployee {
-
- private String id;
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
- }
-
- /**
- * 学校管理类
- */
- class SchoolManager {
- //返回学校总部的员工
- public List
getAllEmployee() { - List
list = new ArrayList<>(); - //这里我们增加了5个员工到list
- for (int i = 0; i < 5; i++) {
- SchoolEmployee emp = new SchoolEmployee();
- emp.setId("学校总部员工id= " + i);
- list.add(emp);
- }
- return list;
- }
-
- /**
- * 该方法完成输出学校总部和学院员工信息(id)
- *
- * @param collegeManager 管理学院员工的管理类
- */
- void printAllEmployee(CollegeManager collegeManager) {
- //只提供方法,不把具体实现放在其他类里面。
- collegeManager.printCollegeEmployee();
- //获取到学校总部员工
- List
list = this.getAllEmployee(); - System.out.println("------学校总部员工------");
- for (SchoolEmployee e : list) {
- System.out.println(e.getId());
- }
- }
- }
合成复用原则 尽量使用组合/聚合的方式,而不是使用继承。
- package com.taoke.principle;
-
- /**
- * 合成复用原则
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class CompositeReuse {
- public static void main(String[] args) {
- System.out.println("------依赖------");
- B b = new B();
- b.Operation1(new A());
-
- System.out.println("------聚合------");
- b.setA(new A());
- b.Operation2();
-
- System.out.println("------组合------");
- b.Operation3();
- }
-
- static class A {
- void Operation1() {
- System.out.println("A Operation1");
- }
-
- void Operation2() {
- System.out.println("A Operation2");
- }
-
- void Operation3() {
- System.out.println("A Operation3");
- }
- }
-
- /**
- * 如果只是需要用到 A类的方法,尽量不要使用继承。而是使用,依赖,聚合,组合的方式
- */
- static class B {
- /**
- * 依赖
- *
- * @param a 实例a
- */
- void Operation1(A a) {
- a.Operation1();
- a.Operation2();
- a.Operation3();
- }
-
- //==============================================================
- A a;
-
- public void setA(A a) {
- this.a = a;
- }
-
- /**
- * 聚合
- */
- void Operation2() {
- a.Operation1();
- a.Operation2();
- a.Operation3();
- }
-
- //==============================================================
- A a1 = new A();
-
- /**
- * 组合
- */
- void Operation3() {
- a1.Operation1();
- a1.Operation2();
- a1.Operation3();
- }
- }
- }
只要是在类中用到了对方,那么他们之间就存在依赖关系。
- package com.taoke.relation;
-
- /**
- * 依赖关系
- * 1、类中用到了对方
- * 2、类的成员属性
- * 3、方法的返回类型
- * 4、方法接收的参数类型
- * 5、方法中使用到
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class Dependence {
- /**
- * 类的成员属性
- */
- A a;
-
- public A save(B b) {//方法接收的参数类型
- System.out.println();
- //方法中使用到
- A a = new A();
- //方法的返回类型
- return a;
- }
- }
-
- class A {
- }
-
- class B {
- }
泛化关系实际上就是继承关系,依赖关系的特例
- package com.taoke.relation;
-
- /**
- * 继承
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class Generalization extends Base {
-
- @Override
- public void get(Object oId) {
-
- }
-
- @Override
- public void put(Object oName) {
-
- }
- }
-
- abstract class Base {
- abstract public void get(Object oId);
-
- abstract public void put(Object oName);
- }
实现关系实际上就是 A类 实现 B接口,依赖关系的特例。
- package com.taoke.relation;
-
- /**
- * 实现
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class Implementation implements Interface {
- @Override
- public void init() {
- System.out.println("init");
- }
- }
-
- interface Interface {
- void init();
- }
类与类之间的关系,依赖关系的特例。关联具有导航性,即双向关系或单向关系。
- package com.taoke.relation;
-
- /**
- * 关联
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class Association {
- class Person {
- private IDCard idCard;
- }
-
- class IDCard {
- private Person person;
- }
- }
-
表示的是整体和部分的关系,整体与部分可以分开,关联关系的特例;聚合关系是关联关系的特例,所以他具有关联的导航性与多重性。
- package com.taoke.relation;
-
- /**
- * 聚合
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class Aggregation {
-
- class Computer {
- private Mouse mouse;
- private Keyboard keyboard;
-
- public void setMouse(Mouse mouse) {
- this.mouse = mouse;
- }
-
- public void setKeyboard(Keyboard keyboard) {
- this.keyboard = keyboard;
- }
- }
-
- class Mouse {
- }
-
- class Keyboard {
- }
- }
-
-
整体与部分的关系,但是整体与部分不可以分开,关联关系的特例。级联删除就是组合关系。
- package com.taoke.relation;
-
- /**
- * 组合
- *
- * @author taoke
- * @date 2022/7/29
- */
- public class Composite {
-
- public class Computer {
- private CPU cpu = new CPU();
- private SSD ssd = new SSD();
- }
-
- static class CPU {
- }
-
- static class SSD {
- }
- }