不搞大理论,一句话带你理解设计模式七大原则

文章目录

  • 口诀记忆
  • 1.单一职责原则
  • 2.开闭原则
  • 3.里氏代换原则
  • 4.依赖倒转原则
  • 5.接口隔离原则
  • 6.合成复用原则
  • 7.迪米特法则

口诀记忆

一(单一职责)段历史(里氏代换),不能被低迷(迪米特)的人所开(开闭原则)辟,因为他们太依赖(依赖倒转)反复(合成复用)去用借口(接口隔离)逃避。

1.单一职责原则

定义:一个类而言,应该只有一个引起它变化的原因

案例: 比如咱们写个订单模块和用户模块,都是分别创建了2个类,一个是orderController和userController,这里就体现了单一职责原则。总不可能所有的controller 都在写在一起呀。

总结:分别功能的不同,写不同类

2.开闭原则

定义:软件实体应尽量在不修改原有代码的情况下进行扩展

案例:这里的支付,如果接受参数改为类的话,可能要要根据新类的出现,继续增加方法,如果该接口就可以解决这个问题

public interface Pay {
     
    // 支付
    void pay();
}
public class AliPay implements Pay {
     
    @Override
    public void pay() {
     
        System.out.println("正在使用支付宝支付");
    }
}
public class WXPay implements Pay{
     
    @Override
    public void pay() {
     
        System.out.println("正在使用微信支付");
    }
}
// 客户端调用-押金支付选择支付手段
public class DepositPay {
     
    // 支付方式 (这边可以通过依赖注入的方式来注入)
    // 支付方式可以写在配置文件中
    // 现在不管你选用何种方式,我都不需要更改
    @Autowired
    Pay payMode;
    void pay(Pay payMode){
     
        payMode.pay();
    }
}

总结:方法的参数最好改为接口的形式

3.里氏代换原则

定义:所有引用基类(父类的)地方都可以用子类来替换,且程序不会有任何的异常。但是反过来就不行,所有使用子类的地方则不一定能用基类来替代,很简单的例子狗是动物,不能说动物是狗,因为可能还有猫。。。。

案例:其实就是继承父类的是时候,new的时候,指定子类 Father f = new Son();

import  java.util.HashMap;
public  class  Father {
     
     public  void  func(HashMap m){
     
         System.out.println( "执行父类..." );
     }
}
 
import  java.util.Map;
public  class  Son  extends  Father{
     
     public  void  func(Map m){
      //方法的形参比父类的更宽松
         System.out.println( "执行子类..." );
     }
}
 
import  java.util.HashMap;
public  class  Client{
     
     public  static  void  main(String[] args) {
     
         Father f =  new  Son(); //引用基类的地方能透明地使用其子类的对象。
         HashMap h =  new  HashMap();
         f.func(h);
     }
}

总结:继承的父类,可以自由添加方法,声明的时候指明子类的对象

4.依赖倒转原则

定义:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。
案例:其实和开闭原则差不多。注意接收参数是接口

public interface Pay {
     
    // 支付
    void pay();
}
public class AliPay implements Pay {
     
    @Override
    public void pay() {
     
        System.out.println("正在使用支付宝支付");
    }
}
public class WXPay implements Pay{
     
    @Override
    public void pay() {
     
        System.out.println("正在使用微信支付");
    }
}
// 客户端调用-押金支付选择支付手段
public class DepositPay {
     
    // 支付方式 (这边可以通过依赖注入的方式来注入)
    // 支付方式可以写在配置文件中
    // 现在不管你选用何种方式,我都不需要更改
    @Autowired
    Pay payMode;
    void pay(Pay payMode){
     
        payMode.pay();
    }
}

总结:其实就是面向接口编程,接受参数变为接口即可

5.接口隔离原则

定义:使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口,类间的依赖关系应该建立在最小的接口上
案例:其实就类似前面的讲的controller要分别定义不同的模块,接口也是, 类在继承接口的时候,要继承与最小接口

错误案例

public interface IAnimal{
     
        /**
         * 吃饭
         */
        void eat();

        /**
         * 工作
         */
        void work();

        /**
         * 飞行
         */
        void  fly();
    }
 public class Tony implements IAnimal{
     

        @Override
        public void eat() {
     
            System.out.println("tony吃");
        }

        @Override
        public void work() {
     
            System.out.println("tony工作");
        }

        @Override
        public void fly() {
     
            System.out.println("tony不会飞");
        }
    }
public class Bird implements IAnimal{
     

        @Override
        public void eat() {
     
            System.out.println("鸟吃");
        }

        @Override
        public void work() {
     
            System.out.println("鸟工作");
        }

        @Override
        public void fly() {
     
            System.out.println("鸟飞");
        }
    }
```java

正确案例

```css
/**
 * 抽象动物的行为
 */
public interface IAnimal {
     
    /**
     * 吃饭
     */
    void eat();

    /**
     * 睡觉
     */
    void sleep();
}
/**
 * 高级动物人 的行为
 */
public interface IAdvancedAnimalBehavior {
     
    /**
     * 打牌
     */
    void playCard();

    /**
     * 骑车
     */
    void byBike();
}
/**
 * 低级动物的行为
 */
public interface IJuniorAnimalBehavior {
     
    /**
     * fly
     */
    void fly();
}
/**
 * 实现高级动物人的共通方法
 */
public class AbstractAdvancedAnimal implements IAnimal {
     
    @Override
    public void eat() {
     
        System.out.println("人吃");
    }

    @Override
    public void sleep() {
     
        System.out.println("人睡");
    }
}
/**
 * 实现低级动物人的共通方法
 */
public class AbstractJuniorAnimal implements IAnimal {
     
    @Override
    public void eat() {
     
        System.out.println("动物吃");
    }

    @Override
    public void sleep() {
     
        System.out.println("动物睡");
    }
}
// tony
public class Tony extends AbstractAdvancedAnimal implements IAdvancedAnimalBehavior {
     
    @Override
    public void playCard() {
     
        System.out.println("tony打牌");
    }

    @Override
    public void byBike() {
     
        System.out.println("tony骑车");
    }
}
// 鸟
public class Bird extends AbstractJuniorAnimal implements IJuniorAnimalBehavior{
     
    @Override
    public void fly() {
     
        System.out.println("鸟飞");
    }
}

总结:每个接口都要细分开来,就类似 一个是orderController和userController

6.合成复用原则

定义:尽量使用对象组合,而不是继承来达到复用的目的
案例

1.3 问题由来

汽车按“动力源”划分可分为汽油汽车、电动汽车等;按“颜色”划分可分为白色汽车、黑色汽车和红色汽车等。如果同时考虑这两种分类,其组合就有6种。将上述业务用代码实现,如果只用继承复用,那么最后有6个子类白色油车、黑色油车、红色油车、白色电动汽车、黑色电动汽车、红色电动汽车。这种情况实现方式,会导致子类过多的情况出现。 并且当增加新的“动力源”或者增加新的“颜色”都要修改源代码,这违背了开闭原则,显然不可取。

先来看一下有问题的代码。

public abstract class Car
{
     
     abstract void run();
}

public class ElectricCar extends Car 
{
     

	@Override
	void run() 
	{
     
		System.out.println("电动汽车");
	}

}

public class PetrolCar extends Car {
     

	@Override
	void run() 
	{
     
		System.out.println("汽油汽车");
	}

}

public class BlackElectricCar extends ElectricCar
{
     
	
	public void appearance()
	{
     
		System.out.print("黑色");
		super.run();
	}
}
public class BlackPetrolCar  extends PetrolCar
{
     
	public void appearance()
	{
     
		System.out.print("黑色");
		super.run();
	}
}

public class RedElectricCar extends ElectricCar 
{
     
	public void appearance()
	{
     
		System.out.print("红色");
		super.run();
	}
}


public class RedPetrolCar  extends PetrolCar
{
     
	public void appearance()
	{
     
		System.out.print("红色");
		super.run();
	}
}
public class WhiteElectricCar extends ElectricCar
{
     
	
	public void appearance()
	{
     
		System.out.print("白色");
		super.run();
	}
}

public class WhitePetrolCar  extends PetrolCar
{
     
	public void appearance()
	{
     
		System.out.print("白色");
		super.run();
	}
}

public class Test {
     
	
	public static void main(String[] args) {
     
		RedElectricCar redElectricCar = new RedElectricCar();
		redElectricCar.appearance();//红色电动汽车
	}

}

采用组合或聚合复用方式,第一步先将将颜色Color抽象为接口,有白色,黑色,红色三个颜色实现类,第二步将Color对象组合在汽车Car类中,最终我们只需要生成5个类,就可以实现上诉功能。同时当增加新的“动力源”或者增加新的“颜色,都不要修改源代码,只要增加实现类就可以。

public abstract class Car
{
     
     abstract void run();
     
     Color color;
	 public Color getColor() {
     
	 	return color;
	 }
	 public void setColor(Color color) {
     
		this.color = color;
	 }
}
public interface Color 
{
     
      void colorKind();
}
public class ElectricCar extends Car 
{
     

	@Override
	void run() 
	{
     
		System.out.println("电动汽车");
	}

}
public class PetrolCar extends Car {
     

	@Override
	void run() 
	{
     
		System.out.println("汽油汽车");
	}

}
public class White implements Color{
     

	@Override
	public void colorKind() 
	{
     
		System.out.println("白色");
	}

}
public class Black implements Color{
     

	@Override
	public void colorKind() 
	{
     
		System.out.println("黑色");
	}

}
public class Red implements Color{
     

	@Override
	public void colorKind() 
	{
     
		System.out.println("红色");
	}

}
public class Test 
{
     
    public static void main(String[] args) 
    {
     
    	ElectricCar electricCar = new ElectricCar();
    	White color = new White();
    	electricCar.setColor(color);
    	electricCar.getColor().colorKind();//白色
    	electricCar.run();//电动汽车
	}
}

总结:最好用依赖注入代替继承

7.迪米特法则

一个软件实体应当尽可能少地与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位

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

  • Only talk to your immediate
    friends(只与直接的朋友通讯),一个对象的"朋友"包括他本身(this)、它持有的成员对象、入参对象、它所创建的对象。
  • 尽量少发布public的变量和方法,一旦公开的属性和方法越多,修改的时候影响的范围越大。
  • “是自己的就是自己的”,如果一个方法放在本类中,既不产生新的类间依赖,也不造成负面的影响,那么次方法就应该放在本类中。
public class Jia{
     
    private Friend friend;

    public Friend getFriend() {
     
        return friend;
    }

    public void setFriend(Friend friend) {
     
        this.friend = friend;
    }

    public void play(Friend friend){
     
        friend.play();
    }
}

//朋友

public class Friend {
     
    public void play(){
     
        System.out.println("朋友");
    }

    public void playWithStranger() {
     
        Stranger stranger = new Stranger();
        stranger.play();
    }
}
public class Stranger {
     
     public void play(){
     
         System.out.println("陌生人");
     }
 }

总结:和自己关系性不大的类,成员,有相关对象的实例。

你可能感兴趣的:(Java,设计模式)