单一职责原则
不符合单一职责原则情况
package com.lvqiang.principle.singleResponsibilityPrinciple;
public class SingleResponsibilityPrinciple {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.run("汽车");
vehicle.run("火车");
vehicle.run("飞机");
}
}
class Vehicle{
public void run(String vehicle){
System.out.println(vehicle + "在公路上行驶....");
}
}
/*
* 从运行结果来看该种方式违背了单一职责原则,不同的交通工具共用一个方法,无法对某一交通工具进行单独特殊处理,
* 需要进行优化
* */
改进1
package com.lvqiang.principle.singleResponsibilityPrinciple;
public class SingleResponsibilityPrinciple2 {
public static void main(String[] args) {
RoadVehicle roadVehicle = new RoadVehicle();
roadVehicle.run("汽车");
WaterVehicle waterVehicle = new WaterVehicle();
waterVehicle.run("轮船");
RailwayVehicle railwayVehicle = new RailwayVehicle();
railwayVehicle.run("高铁");
}
}
class RoadVehicle{
public void run(String vehicle){
System.out.println(vehicle + "在公路上行驶....");
}
}
class WaterVehicle{
public void run(String vehicle){
System.out.println(vehicle + "在水面行驶....");
}
}
class RailwayVehicle{
public void run(String vehicle){
System.out.println(vehicle + "在铁路上行驶....");
}
}
/**
* 此种方式遵从了在方法上和类上职责单一原则,属于高度的单一,但是此种方式成本较高,有时会有些
*
*/
改进二
package com.lvqiang.principle.singleResponsibilityPrinciple;
public class SingleResponsibilityPrinciple3 {
public static void main(String[] args) {
Vehicles vehicles = new Vehicles();
vehicles.roadRun("汽车");
vehicles.waterRun("轮船");
vehicles.railwayRun("高铁");
}
}
class Vehicles{
public void roadRun(String vehicle){
System.out.println(vehicle + "在公路上行驶....");
}
public void waterRun(String vehicle){
System.out.println(vehicle + "在水面行驶....");
}
public void railwayRun(String vehicle){
System.out.println(vehicle + "在铁路上行驶....");
}
}
/**
* 该方式实现了方法上的单一职责原则, 当有新的运行方式时直接在类上新增相应方法即可。
*
* 但是该类违反了类级别的单一原则,这是因为如果将每个交通方式都抽取出一个类,类中只有一个方法,像这种
* 类中方法足够简单即可在一定程度上违背单一职责原则。
*/
接口隔离原则
如图:此时如果所有功能都集中在一个接口中,如果此时某个类只需用到其中某几个方法,而此时还是不得不实现该接口并实现接口中所有的方法。这样造成了代码将耦合性较高,不得不实现一些没必要的方法。不符合接口隔离原则。 需要进行细分,拆分成多个接口。
将之前那个大的接口拆分成几个独立的接口,实现了接口隔离,降低了耦合性。
-
那么为什么不直接将所有接口都拆分成一个个独立的呢?
如果是这样拆分,虽然确实实现了接口隔离原则 ,但是拆分粒度不免会有些过于细,在实现接口时不免有些过于累赘,大部分情况下都无需拆分过于精细。
依赖倒置原则
未遵守依赖倒置原则出现问题
package com.lvqiang.principle.singleResponsibilityPrinciple.dependencyInversionPrinciple;
public class DependencyInversionPrinciple1 {
public static void main(String[] args) {
Person person = new Person();
Email email = new Email();
person.receive(email);
WeiXin weiXin = new WeiXin();
person.receive(weiXin);
}
}
class Person{
public void receive(Email email){
email.getMsg();
}
public void receive(WeiXin weiXin){
weiXin.getMsg();
}
}
class Email{
public void getMsg(){
System.out.println("Email info....");
}
}
class WeiXin{
public void getMsg(){
System.out.println("WeiXin info....");
}
}
/**
* 如果是使用此方法实现,功能确实能实现,可当我们后续需要再新增其他通讯方式如QQ 等既需要新增QQ类, 还需要在Person中昨天qq相对应的获取信息的方式
* 代码改动较大,针对这种情况便可使用控制反转,抽取出一个通用的功能接口,通过接口传递来实现。
*
*/
使用依赖倒置带来的好处
package com.lvqiang.principle.singleResponsibilityPrinciple.dependencyInversionPrinciple;
public class DependencyInversionPrinciple2 {
public static void main(String[] args) {
Person2 person = new Person2();
Receive receive= new Email2();
person.receive(receive);
receive = new WeiXin2();
person.receive(receive);
}
}
class Person2{
public void receive(Receive receive){
receive.getMsg();
}
}
interface Receive{
public void getMsg();
}
class Email2 implements Receive{
public void getMsg(){
System.out.println("Email info....");
}
}
class WeiXin2 implements Receive{
public void getMsg(){
System.out.println("WeiXin info....");
}
}
/**
* 通过使用依赖倒置,使使用的类都依赖于公共的接口,极大的方便了程序的扩展,用法也更加灵活多变。
*
* 实现方式可以有三种:
* 1.接口传递
* 2.构造方法传递
* 3.setter方法传递
*
*/
//2.构造方法传递
//class Person2{
// Receive receive;
// public Person2(Receive receive){
// this.receive = receive;
// }
// public void receive(){
// receive.getMsg();
// }
//}
//3.setter方法传递
//class Person2{
// Receive receive;
//
// public void setReceive(Receive receive){
// this.receive = receive;
// }
// public void receive(){
// receive.getMsg();
// }
//}
里氏替换原则
子类可以替换父类出现在父类能够出现的任何地方(即尽量不要重写父类中的方法),其实使用继承会使得使这两个类耦合性增加了,给程序带来了侵入性,可以通过使用组合、聚合和依赖来实现。
开闭原则
方式一:
package com.lvqiang.principle.singleResponsibilityPrinciple.openClosePrinciple;
/**
* 需求:实现一个可以画任意图形功能
*
*/
public class OpenClosePrinciple1 {
public static void main(String[] args) {
ShapEdite shapEdite = new ShapEdite();
shapEdite.drawShap(new Circular());
}
}
class ShapEdite{
public void drawShap(Shap s){
if(s.s_type == 0){
System.out.println("无图形");
}else if (s.s_type == 1){
drawCircular();
}else if(s.s_type == 2){
drawRectangle();
}else{
drawTriangle();
}
}
public void drawCircular(){
System.out.println("画圆形");
}
public void drawRectangle(){
System.out.println("画矩形");
}
public void drawTriangle(){
System.out.println("画三角形");
}
}
abstract class Shap{
int s_type;
}
class Circular extends Shap{
public Circular() {
super.s_type = 1;
}
}
class Rectangle extends Shap{
public Rectangle() {
super.s_type = 2;
}
}
class Triangle extends Shap{
public Triangle() {
super.s_type = 3;
}
}
/**
* 此种实现方式存在的弊端:当每新增一个新的图形时,不但需要编写新的图形类,还需要再ShapEdite类中增加新的类型判断,不符合开闭原则的设计
* 同时也违背了中少用if-else 判断。
* 改进:使用策略模式代替if-else , 将通用的画图方法抽取到出来 放在抽象类中。
*/
方式二
package com.lvqiang.principle.singleResponsibilityPrinciple.openClosePrinciple;
/**
* 需求:实现一个可以画任意图形功能
*/
public class OpenClosePrinciple2 {
public static void main(String[] args) {
ShapEdite2 shapEdite2 = new ShapEdite2();
shapEdite2.drawShap(new Rectangle2());
}
}
class ShapEdite2 {
public void drawShap(Shap2 s) {
s.draw();
}
}
abstract class Shap2 {
int s_type;
public abstract void draw();
}
class Circular2 extends Shap2 {
@Override
public void draw() {
System.out.println("画圆形");
}
}
class Rectangle2 extends Shap2 {
@Override
public void draw() {
System.out.println("画矩形");
}
}
class Triangle2 extends Shap2 {
@Override
public void draw() {
System.out.println("画三角形");
}
}
/**
* 当还需要再增加需求时,直接通过新增实体类即可达到应对 变化的需求,而无需修改已有的代码。
* 只是对模块的扩张方面开放(新实体类的增加), 而对代码的就该关闭(修改EditeShap类)。遵从了开闭的原则
* 同时使用了策略模式避免出现了大量的if-else的判断
*/