zl程序教程

您现在的位置是:首页 >  其他

当前栏目

设计模式——七大原则

设计模式 原则 七大
2023-09-27 14:28:31 时间

汇总篇

1、单一职责

对类来说的,即一个类应该只负责一项职责。如类A负责两个不同职责:职责1,职责2。当职责一需求变更而改变A时,可能照成职责2执行错误,所以需要将类A的粒度分解为A1,A2。

在这里插入图片描述

违背原则示例:

public static void run(Integer type,String vehicle) {
	if (type == 1){
		System.out.println(vehicle + "在公路上运行");
	}else if (type == 2){
		System.out.println(vehicle + "在天空飞");
	}else {
		System.out.println(vehicle + "在水里游");
	}
}

符合原则代码:
1、这种方法没有对原来的类做大的修改,只是增加方法。
2、这里虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然是遵守单一职责。

public class Only {

	public static void run(String vehicle) {
		System.out.println(vehicle + "在公路上运行");
	}

	public static void runAir(String vehicle) {
		System.out.println(vehicle + "在天空飞");
	}

	public static void runWater(String vehicle) {
		System.out.println(vehicle + "在水里游");
	}
}

单一职责原则注意事项与细节:

  • 降低类的复杂度,一个类只负责一项职责。
  • 降低类的可读性,可维护性
  • 降低变更引起的风险
  • 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责

2、接口隔离

客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。

在这里插入图片描述
就是将一个类拥有很多接口拆成多个类较少接口,实现接口隔离,不需要引入不需要的接口。

在这里插入图片描述
违背原则示例:

public interface interface0{
		void operation1(); // 产品
		
		void operation2(); // 程序员1号
		
		void operation3(); // 程序员2号
		
		void operation4(); // 测试
		 
		void operation5(); // 运维
	}
// 实现类
static class work implements interface0{

		@Override
		public void operation1() {}

		@Override
		public void operation2() {}

		@Override
		public void operation3() {}

		@Override
		public void operation4() {}

		@Override
		public void operation5() {}
	}

符合原则代码:

public class Segregation {
/**
 * ---------------------------------拆开多个接口---------------------------------------------
 */
  public interface interface1{ // 产品接口
		void operation1(); 
	}
  public interface interface2{ // 程序员
		void operation2();
		void operation3();
	}
  public interface interface3{ // 测试
		void operation4();
	}
	/**
	 * ---------------------------------类实现接口---------------------------------------------
	 */
	static class B implements interface2{
		@Override
		public void operation2() {
			System.out.println("B实现接口2的方法");
		}
		@Override
		public void operation3() {
			System.out.println("B实现接口2的方法");
		}
	}
}

static class B implements interface3{
		@Override
		public void operation4() {
			System.out.println("B实现接口3的方法");
		}
}

使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。


3、依赖倒转

  • 1、高层模块不应该依赖低层模块,二者都应该依赖其抽象。
  • 2、抽象不应该依赖细节,细节应该依赖抽象
  • 3、依赖倒转的中心思想是面向接口编程
  • 4、依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类。
  • 5、使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。

在这里插入图片描述

违背原则代码

	public static void main(String[] args) {
		Person person = new Person();
		Email email = new Email();
		person.IReceiver(email); 
	}
	public static class Person{ // 接收人
		public void IReceiver(Email email){
			System.out.println(email.info());
		}
	}
	public static class Email{
		String info(){
			return "邮件信息";
		}
	}

此时又想接收微信消息,还要再重新修改

符合原则代码:

	public static void main(String[] args) {
	   	IReceiver iReceiver = new Email(); // 接收邮件消息
		System.out.println(iReceiver.getInfo());
		// 要想再接收微信
		IReceiver iReceiver1 = new Weixin();
		System.out.println(iReceiver1.getInfo());
	}



	// 定义接口
	interface IReceiver{
		public String getInfo();
	}

	/**
	 * ---------------------------------以下用实现类来做具体的细节操作---------------------------------------------
	 */
	static class Email implements IReceiver{

		@Override
		public String getInfo() {
			// 这里实现细节
			return "邮件消息";
		}
	}

	static class Weixin implements IReceiver{

		@Override
		public String getInfo() {
			// 这里实现细节
			return "微信消息";
		}
	}

依赖倒转原则的注意事项和细节:
1、低层模块尽量都要有抽象类或接口,或者两者都有,程序稳定性更好。
2、变量的声明类型尽量是抽象类或接口,这样我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化
3、继承是遵守里氏代换原则。


4、里氏代换原则

一、OO中的继承性的思考和说明

  • 1、继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契
    约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实
    现的方法任意修改,就会对整个继承体系造成破坏。

  • 2、继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵
    入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,
    则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子
    类的功能都有可能产生故障

要使用好继承,就要了解里氏代换原则

二、基本了解

  • 1、在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
  • 2、里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可
    通过聚合,组合,依赖 来解决问题
  • 3、如果对每个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序
    P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1
    的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象。
    .

在这里插入图片描述

就是当B类最好不要直接继承A类,去重写它,要再建一个更基础的类,两个都去继承,增强两个类的耦合性

违背原则代码

	class A{
		// 返回两个数的差
		public int func1(int num1,int num2){
			return num1 - num2;
		}
	}
	class B extends A{
		// 返回两个数的和
		public int func2(int num1,int num2){
			return num1 + num2;
		}

		@Override
		public int func1(int num1, int num2) {
			return super.func1(num1, num2);
		}
	}

符合原则代码:

public class Lsdh {

	// 创建一个更加基础的类
	class Base{
		// 把更基础的方法和成员写到Base类
	}
	class A extends Base{
		// 返回两个数的差
		public int func1(int num1,int num2){
			return num1 - num2;
		}
	}
	class B extends Base{
		// 返回两个数的和
		public int func2(int num1,int num2){
			return num1 + num2;
		}
		// 如果B需要使用A类的方法,使用组合关系
		private A a  = new A();
		public int func3(int num1,int num2){
			return a.func1(num1,num2);
		}
	}
}

5、开闭原则

  • 1、 开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则
  • 2、 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。
  • 3、 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
  • 4、 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。

违背原则代码

	public static void main(String[] args) {
		// 画图功能
		GraphicEditor graphicEditor = new GraphicEditor();
		// 画一个正方形
		graphicEditor.draw(1,"正方形");
	}
	static class GraphicEditor{
		public void draw(Integer type,String draw) {
			if (type == 1){
				// 画正方形
			}else if (type == 2){
				// 画长方形
			}
		}
	}

如果要新增功能时,会修改到旧代码,要是旧代码是别人写的,可能会牵一发而动全身,出了好几个bug

符合原则代码

public class Ocp {
	
	public  void main() {
		// 画图功能
		GraphicEditor graphicEditor = new GraphicEditor();
		// 画一个正方形
		graphicEditor.drawShape(new square()); 
		// 如果还要再画一个长方形,不需要改代码,直接扩展
		graphicEditor.drawShape(new rectangle());
	}
	// 要调用画图方法的类
	static class GraphicEditor{
		public void drawShape(draw draw) {
			draw.drawFunc();
		}
	}
	// 定义一个画图接口
	interface draw{
		// 画画的方法
		void drawFunc();
	}
	// 实现画图接口,作画
	class  square implements draw{

		@Override
		public void drawFunc() {
			System.out.println("画了个正方形!");
		}
	}
	// 实现画图接口,作画
	class rectangle implements draw{

		@Override
		public void drawFunc() {
			System.out.println("画了个长方形!");
		}
	}
}

这个原则讲的就是,将代码写的扩展性高点,如果新增功能,不用去改旧代码,直接新增新的功能


6、迪米特法则

一、基本介绍

  • 1、迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的
    越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内
    部。对外除了提供的public 方法,不对外泄露任何信息

  • 2、一个对象应该对其他对象保持最少的了解

在这里插入图片描述

违法原则代码

	    // 咖啡类
    static class coffee{
		//泡咖啡
		public void make(){
			// 1、烧水
			// 2、磨咖啡粉
			// 3、泡

		}
		// 找秘书过来
		public String secretary(){
			return "过来";
		}
	}

	public static void main(String[] args) {
		coffee coffee = new coffee();
		coffee.make();
		coffee.secretary();
	}

符合原则代码:

    // 咖啡类
    static class coffee{
		//泡咖啡
		public void make(){
			// 1、烧水
			// 2、磨咖啡粉
			// 3、泡

		}
		// 找秘书,秘书泡好端过来
		public String secretaryMake(){
			make();
			return "coffee";
		}
	}

	public static void main(String[] args) {
		// 老板想找助理干活,还想喝coffee,直接叫助理泡好过来
		coffee coffee = new coffee();
		coffee.secretaryMake();
	}

三、注意事项

  • 迪米特法则的核心是降低类之间的耦合
  • 但是要注意:由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系,并不是要求完全没有依赖关系。

7、合成复用

一、基本介绍

尽量使用合成/聚合的方式,而不是使用继承

在这里插入图片描述
违背原则代码

	static class A {
		public void method1(){
			System.out.println("你调用了方法一");
		}

		public void method2(){
			System.out.println("你调用了方法二");
		}
	}
	// B类继承A
	static class B extends A{
		
	}
	
	public static void main(String[] args) {
		B b = new B();
		b.method1();
		b.method2();
	}

使用继承方式,B类继承了A类之后,就可以使用了A类中的两个方法,这样耦合性较高,不推荐

符合原则代码

/**
 * ---------------------------------组合方式---------------------------------------------
 */
	static class B{
		A a = new A();

		public void method1(){
			a.method1();
		}

		public void method2(){
			a.method2();
		}
	}

	public static void main(String[] args) {
		B b = new B();
		b.method2();
		b.method1();
	}
/**
 * ---------------------------------依赖方式---------------------------------------------
 */
	static class B{
		
		public void method1(A a){
			a.method1();
		}

		public void method2(A a){
			a.method2();
		}
	}

组合/聚合的方式,在B类里注入A,通过注入的A类来调用方法,耦合性低,易扩展。符合合成复用的原则
依赖方式,把A类作为参数传递到B类的两个方法中,从而达到调用A类的方法,耦合性低。符合合成复用的原则

核心思想

  • 1、找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起
  • 2、针对接口编程,而不是针对实现编程
  • 3、为了交互对象之间的松耦合设计而努力