网站建设 统一质量标准,无锡手机网站建设服务,做网站策划案,iis6.0做网站压缩目录一、单一职责二、接口隔离三、依赖倒置#xff08;倒转#xff09;四、里氏替换五、迪米特法则#xff08;Law of Demeter#xff09;六、开闭七、合成复用一、单一职责 类#xff08;或方法#xff09;功能的专一性。一个类#xff08;或方法#xff09;不应该承担…
目录一、单一职责二、接口隔离三、依赖倒置倒转四、里氏替换五、迪米特法则Law of Demeter六、开闭七、合成复用一、单一职责 类或方法功能的专一性。一个类或方法不应该承担太多功能一个类或方法最好只承担 一种类型 的功能。
public class SingleResponsibility {public static void main(String[] args) {Vehicle vehicle new Vehicle();vehicle.run(汽车);vehicle.run(火车);vehicle.run(自行车);vehicle.run(飞机); // 有问题vehicle.run(轮船); // 有问题}
}class Vehicle {public void run(String vehicleName) {System.out.println(vehicleName 在公路上行驶);}
}Vehicle 类既处理陆地上的交通工具又处理天空中的交通工具它的作用太广泛了不单一。 public class SingleResponsibility {public static void main(String[] args) {RoadVehicle roadVehicle new RoadVehicle();roadVehicle.run(汽车);roadVehicle.run(火车);roadVehicle.run(自行车);SkyVehicle skyVehicle new SkyVehicle();skyVehicle.run(飞机);WaterVehicle waterVehicle new WaterVehicle();waterVehicle.run(轮船);}
}class RoadVehicle {public void run(String vehicleName) {System.out.println(vehicleName 在公路上行驶);}
}class WaterVehicle {public void run(String vehicleName) {System.out.println(vehicleName 在水中行驶);}
}class SkyVehicle {public void run(String vehicleName) {System.out.println(vehicleName 在天空中行驶);}
}在类级别遵循了单一职责原则 当业务功能比较简单的时候也没有必要将其拆分为多个类如下所示 public class SingleResponsibility {public static void main(String[] args) {Vehicle vehicle new Vehicle();vehicle.run(汽车, VehicleType.ROAD);vehicle.run(火车, VehicleType.ROAD);vehicle.run(自行车, VehicleType.ROAD);vehicle.run(飞机, VehicleType.SKY);vehicle.run(轮船, VehicleType.WATER);}
}enum VehicleType {ROAD, WATER, SKY;
}class Vehicle {public void run(String name, VehicleType type) {String sentence ;if (type VehicleType.ROAD) {sentence 在公路上行驶;} else if (type VehicleType.WATER) {sentence 在水中行驶;} else if (type VehicleType.SKY) {sentence 在天空中行驶;}System.out.println(name sentence);}// public void roadRun(String name) {}// public void skyRun(String name) {}// public void waterRun(String name) {}
}Vehicle 类不符合单一职责原则但其功能简单 。 当功能非常非常简单的时候不一定必须遵循单一职责原则。杀鸡别用宰牛刀 降低了类的功能的复杂度提高了代码的维护性代码修改导致连带错误几率降低 二、接口隔离 ① Clients should not be forced to depend on methods they do not use. 客户端不应该被迫依赖它不使用的方法。 ② The dependency of one class to another one should depend on the smallest possible interface. 一个类对另一个类的依赖应该建立在最小的接口上。 public class InterfaceSegregation {public static void main(String[] args) {InOutAbleImpl1 impl1 new InOutAbleImpl1();InOutAbleImpl2 impl2 new InOutAbleImpl2();Cat cat new Cat();cat.use1(impl1);cat.use2(impl1);cat.use3(impl1);Dog dog new Dog();dog.use1(impl2);dog.use2(impl2);dog.use3(impl2);}
}class Cat {public void use1(InOutAble inOutAble) {inOutAble.openDoor();}public void use2(InOutAble inOutAble) {inOutAble.pushGoods();}public void use3(InOutAble inOutAble) {inOutAble.writeGoodsName();}
}class Dog {public void use1(InOutAble inOutAble) {inOutAble.openDoor();}public void use2(InOutAble inOutAble) {inOutAble.popGoods();}public void use3(InOutAble inOutAble) {inOutAble.writePeopleName();}
}/*** 存取东西的接口*/
interface InOutAble {// 类型1void openDoor(); // 打开门// 类型2void pushGoods(); // 放入货物void writeGoodsName(); // 登记货物名字// 类型3void popGoods(); // 取出货物void writePeopleName(); // 登记取货人的名字
}class InOutAbleImpl1 implements InOutAble {Overridepublic void openDoor() {System.out.println(InOutAbleImpl1 - openDoor);}Overridepublic void pushGoods() {System.out.println(InOutAbleImpl1 - pushGoods);}Overridepublic void writeGoodsName() {System.out.println(InOutAbleImpl1 - writeGoodsName);}Overridepublic void popGoods() {System.out.println(InOutAbleImpl1 - popGoods);}Overridepublic void writePeopleName() {System.out.println(InOutAbleImpl1 - writePeopleName);}
}class InOutAbleImpl2 implements InOutAble {Overridepublic void openDoor() {System.out.println(InOutAbleImpl2 - openDoor);}Overridepublic void pushGoods() {System.out.println(InOutAbleImpl2 - pushGoods);}Overridepublic void writeGoodsName() {System.out.println(InOutAbleImpl2 - writeGoodsName);}Overridepublic void popGoods() {System.out.println(InOutAbleImpl2 - popGoods);}Overridepublic void writePeopleName() {System.out.println(InOutAbleImpl2 - writePeopleName);}
}public class InterfaceSegregation {public static void main(String[] args) {OpenPushImpl impl1 new OpenPushImpl();OpenPopImpl impl2 new OpenPopImpl();Cat cat new Cat();cat.use1(impl1);cat.use2(impl1);cat.use3(impl1);Dog dog new Dog();dog.use1(impl2);dog.use2(impl2);dog.use3(impl2);}
}class Cat {public void use1(OpenPushImpl openPushImpl) {openPushImpl.openDoor();}public void use2(OpenPushImpl openPushImpl) {openPushImpl.pushGoods();}public void use3(OpenPushImpl openPushImpl) {openPushImpl.writeGoodsName();}
}class Dog {public void use1(OpenPopImpl openPopImpl) {openPopImpl.openDoor();}public void use2(OpenPopImpl openPopImpl) {openPopImpl.popGoods();}public void use3(OpenPopImpl openPopImpl) {openPopImpl.writePeopleName();}
}interface OpenDoorAble {void openDoor(); // 打开门
}interface PushAble {void pushGoods(); // 放入货物void writeGoodsName(); // 登记货物名字
}interface PopAble {void popGoods(); // 取出货物void writePeopleName(); // 登记取货人的名字
}class OpenPushImpl implements OpenDoorAble, PushAble {Overridepublic void openDoor() {System.out.println(OpenPushImpl - openDoor);}Overridepublic void pushGoods() {System.out.println(OpenPushImpl - pushGoods);}Overridepublic void writeGoodsName() {System.out.println(OpenPushImpl - writeGoodsName);}
}class OpenPopImpl implements OpenDoorAble, PopAble {Overridepublic void openDoor() {System.out.println(OpenPopImpl - openDoor);}Overridepublic void popGoods() {System.out.println(OpenPopImpl - popGoods);}Overridepublic void writePeopleName() {System.out.println(OpenPopImpl - writePeopleName);}
}三、依赖倒置倒转 ① 高层模块不应该依赖低层模块类二者都应该依赖于抽象接口 ② 抽象接口不应该依赖细节实现类而是细节依赖于抽象 ③ 依赖倒置的中心思想是面向接口抽象编程 ④ 依赖倒置设计理念相对于细节的多变性抽象的东西要稳定得多。以抽象为基础搭建的架构比以细节为基础搭建的架构要稳定 ⑤ 使用接口或抽象类的作用是制定规范协议把展现细节的任务交给接口的实现类 接口 ➡️ 抽象 实现类 ➡️ 细节 public class DependencyInversion {public static void main(String[] args) {Person person new Person();person.sendMessage(new QQMessage(用QQ问候一下小明));person.sendMessage(new WechatMessage(用微信问候一下小明));}
}class Person {public void sendMessage(QQMessage qqMessage) {System.out.println(qqMessage.buildMessage());}public void sendMessage(WechatMessage wechatMessage) {System.out.println(wechatMessage.buildMessage());}
}class QQMessage {private String message;public QQMessage(String message) {this.message message;}public String buildMessage() {return QQ Message: message;}
}class WechatMessage {private String message;public WechatMessage(String message) {this.message message;}public String buildMessage() {return Wechat Message: message;}
} 假如版本升级还想发送 抖音消息 的话① 需要创建一个 TiktokMessage 类② 需要在 Person 类中再重载一个 sendMessage(TiktokMessage tiktokMessage) 方法 每次版本升级增加新的发送消息的方式的时候对代码的改动非常大。假如不止一个用户不仅仅只有 Person 类哪改动就更加巨大了 面向接口编程 public class DependencyInversion {public static void main(String[] args) {Person person new Person();person.sendMessage(new QQMessage(用QQ问候一下小明));person.sendMessage(new WechatMessage(用微信问候一下小明));}
}class Person {public void sendMessage(IMessage iMessage) {System.out.println(iMessage.buildMessage());}
}interface IMessage {String buildMessage();
}/*** 发送 QQ 消息*/
class QQMessage implements IMessage {private String message;public QQMessage(String message) {this.message message;}Overridepublic String buildMessage() {return QQ Message: message;}
}/*** 发送微信消息*/
class WechatMessage implements IMessage {private String message;public WechatMessage(String message) {this.message message;}public String buildMessage() {return Wechat Message: message;}
}四、里氏替换
继承优点 提高代码的复用性子类继承父类后可使用父类的非 private 关键字修饰的的成员
public class Animal {public void eat() {System.out.println(Animal - public void eat());}protected void drink() {System.out.println(Animal - protected void drink());}void play() {System.out.println(Animal - void play());}
}class Dragon extends Animal {public void use() {eat(); // Animal - public void eat()drink(); // Animal - protected void drink()play(); // Animal - void play()}public static void main(String[] args) {Dragon dragon new Dragon();dragon.use();}
}继承缺点: ① 继承关系过去庞大的话整个代码结构会很乱 ② 代码耦合性变高 ③ 代码稳定性变差子类可以重写父类的方法。重写之后运行时究竟调用的是父类的方法还是子类重写的方法很难判断 ④ 如果有多处直接使用父类方法的实现但凡父类方法修改了所有依赖该父类方法的地方都得考虑兼容性考虑代码是否会产生 bug (1) 子类可以实现父类的抽象方法【不要覆盖父类的非抽象方法】 (2) 子类可以可以增加自己特有的实现不要影响父类的非抽象方法【你用父类的可以但不要改】 (3) 子类方法重载父类方法的时候方法的形参要比父类方法的形参更宽松父类方法的形参得是子类方法的形参的父类型
public class Main {public static void main(String[] args) {Parent parent new Parent();parent.m2(new ArrayList());Son son new Son();son.m2(new ArrayList());/*Parent - m2(ArrayListString)Parent - m2(ArrayListString)*/}
}class Parent {public void m1() {System.out.println(Parent - m1());}public void m2(ArrayListString list) {System.out.println(Parent - m2(ArrayListString));}
}class Son extends Parent {// 不符合里氏替换原则子类不应该重写父类的非抽象方法Overridepublic void m1() {System.out.println(Son - m1());}// 子类重载父类的方法子类重载的方法的参数类型要比父类被重载的方法的参数类型大// 这样才符合里氏替换原则, 子类增加代码如新增一个方法不会影响父类方法的使用public void m2(ListString list) {System.out.println(Son - m2(ListString));}
}(4) 子类实现父类的抽象方法的时候方法的返回值应比父类的更加严格 五、迪米特法则Law of Demeter 只与你的直接朋友交谈不与陌生人交谈【降低类与类之间的耦合】 A ➡️ B ➡️ C ① A 和 B 是直接朋友 ② B 和 C 是直接朋友 ③ A 和 C 是陌生人 ④ 若 A 想使用 C 中的方法需要通过 B 直接朋友: ① 当前对象本身 ② 当前对象的成员变量 ③ 当前对象的成员方法的返回类型 ④ 当前对象的成员方法的参数
class Parent {public void m() {// 在方法内部 new 出来的是非直接朋友User user new User();}
} class User {}六、开闭 Open Close Principe软件对象类、模块、方法等应该对扩展开放对修改关闭 用抽象构建框架用实现扩展细节 开放 服务方 的拓展关闭 消费方 的修改 public class OpenClosePrincipe {public static void main(String[] args) {// 对消费方的修改关闭// 尽量少修改原先的代码MilkTeaFactory factory new MilkTeaFactory();factory.makeMilkTea(MilkTeaType.APPLE);factory.makeMilkTea(MilkTeaType.BANANA);}
}interface MilkTeaAble {}class AppleMilkTea implements MilkTeaAble {public AppleMilkTea() {System.out.println(苹果奶茶);}
}class BananaMilkTea implements MilkTeaAble {public BananaMilkTea() {System.out.println(香蕉奶茶);}
}enum MilkTeaType {APPLE, BANANA
}class MilkTeaFactory {public MilkTeaAble makeMilkTea(MilkTeaType type) {switch (type) {case APPLE:return new AppleMilkTea();case BANANA:return new BananaMilkTea();}return null;}
}public class OpenClosePrincipe {// 修改依赖的类型消费方代码没有修改private static MilkTeaAble factory new WatermelonMilkTeaFactory();public static void main(String[] args) {factory.milkTea();}
}interface MilkTeaAble {void milkTea();
}class AppleMilkTeaFactory implements MilkTeaAble {Overridepublic void milkTea() {System.out.println(苹果奶茶);}
}class BananaMilkTeaFactory implements MilkTeaAble {Overridepublic void milkTea() {System.out.println(香蕉奶茶);}
}class WatermelonMilkTeaFactory implements MilkTeaAble {Overridepublic void milkTea() {System.out.println(西瓜奶茶);}
}七、合成复用 通过对象 组合、聚合、依赖 达成代码复用而不是继承
class Animal {public void eat() {System.out.println(Animal - eat());}public void drink() {System.out.println(Animal - drink());}public void play() {System.out.println(Animal - play());}
}/*** 继承不推荐, 不符合合成复用原则*/
class People1 extends Animal {public void use() {eat();drink();play();}
}/*** 依赖推荐*/
class People2 {public void use(Animal animal) {animal.eat();animal.drink();animal.play();}
}/*** 聚合推荐*/
class People3 {private Animal animal;public void setAnimal(Animal animal) {this.animal animal;}public void use() {animal.eat();animal.drink();animal.play();}
}/*** 组合推荐*/
class People4 {private Animal animal new Animal();public void use() {animal.eat();animal.drink();animal.play();}
}