欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)

程序员文章站 2022-03-19 16:10:55
一.设计原则Java的23种设计模式是根据设计原则来的,设计原则实际模式的设计依据.每一个类用来处理一类事物,尽量使用接口进行方法规范(少使用继承),类与类之间尽量使用引用关系。单一原则:一个类只处理一类事物(分为类单一和方法单一)A.类单一B.方法单一接口隔离原则一个类如果只需要一个接口中的部分方法,请将该接口进行分离.一个接口用来处理一类事物隔离原则应当这样处理:将接口 Interface1拆分为独立的几个接口(这里我们拆分成 3 个接口),类 A 和类 C 分别与他...

一.设计原则

Java的23种设计模式是根据设计原则来的,设计原则实际模式的设计依据.

每一个类用来处理一类事物,尽量使用接口进行方法规范(少使用继承),类与类之间尽量使用引用关系。

  1. 单一原则:一个类只处理一类事物(分为类单一和方法单一)
    A.类单一
    设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)
    B.方法单一
    设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)

  2. 接口隔离原则
    一个类如果只需要一个接口中的部分方法,请将该接口进行分离.一个接口用来处理一类事物

设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)
隔离原则应当这样处理:
将接口 Interface1拆分为独立的几个接口(这里我们拆分成 3 个接口),类 A 和类 C 分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则( 每一个类所依赖的接口为最小接口,最小接口就是接口中的规定的方法不要有多余的)

  1. 依赖倒转原则

依赖倒转原则是指:

(1)高层模块不应该依赖低层模块,二者都应该依赖其抽象

(2)抽象不应该依赖细节,细节应该依赖抽象

(3)依赖倒转(倒置)的中心思想是面向接口编程,使用多态(父类引用指向子类对象)

(4)依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java 中,抽象指的是接口或抽象类,细节就是具体的实现类

(5)使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成

  1. 里氏替换原则
  • 在继承的时候,子类无意间重写父类的方法。如果我们对父类中的方法进行了修改,有可能会影响到子类的代码。
  • 继承在给程序设计带来便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障。
  • 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
  • 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖 来解决问题。
  1. 开闭原则
  • 对扩展开放,对修改关闭 .是对父类开放扩展,对子类关闭修改(不要试图修改子类的方式来修改父类)
  • 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
  • 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。

设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)

  1. 迪米特法则:对外暴露越少越好,类与类之间尽量找直接关系。

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

(2)迪米特法则还有个更简单的定义:只与直接的朋友通信

  1. 合成复用原则
  • 就是尽量使用类与类的引用关系来进行方法的调用

例一设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)
例二设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)

合成复用其实就是做类与类的引用

二.设计模式

设计模式是根据设计原则结合实际开发中的方式,进行总结出来的一套编程模式。 根据需求不同分类 :
创建型模式: 主要是用来实例化对象用的 (单例模式、抽象工厂模式、原型模式、建造者模式、工厂模式)
结构型模式: 对象或类的调用(适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式)
行为型模式: 不同类之间的相互处理(模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter 模式)、状态模式、策略模式、职责链模式(责任链模式))

  1. 单例模式
  • 通过类new一次就会得到一个实例对象,多次new得到是不同的对象。

  • 如果需要得到同一个对象:单例模式是通过改变获取java对象的方式得到同一个java对象 (不要使用new的方式来得到java对象) 使用方

  • 为了不让使用方直接使用:将提供方的构造方法私有化

//构造方法
private Student(String name){
	this.name=name;
	}
private Student(){
}

操作是对构造方法私有化,封装的思想,暴露一个得到java的public方法
单例模式就是为了得到相同的对象,不使用new的方式来得到对象(使用方),在本类中将构造方法进行私有化,提供一个返回一个java对象的public方法。那个使用方要一个java对象 就使用我的公共方法得到。
(1)饿汉模式: 管你有没有 我都要创建

  • 使用静态属性来统一java对象
    设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)

  • 使用静态代码块的方式来得到对象

设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)
饿汉模式会导致内存浪费,没有要实例化对象的时候,对象都已经被实例化出来了 。
(2) 懒汉模式
得到对象的时候,第一次进来,如果对象没有被实例化,我们就实例化一个,如果已经实例化了,就直接拿来用就可以了。
设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)

  1. 工厂模式
  • 所谓的工厂就是一个第三方类,工具类。

测试类–>工厂–>Student
(1) 普通工厂
设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)

(2)静态工厂
就是我只需要通过工厂的流水线得到我要的实例化对象,我并不需要工厂对象。
设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)

(3) 抽象工厂

  • 该工厂是一个抽象的, 该工厂自己不会干,找两个实际工厂来做(多态思想 )
  • 抽象工厂自己并不会生产,拥有的是抽象方法,实际根据需要使用多态得到已知实现子类工厂。 实际调用的是非抽象工厂的方法来创建手机对象。
    可以将工厂升级为接口来实现
    作用:对代码的修改维护降低
    设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)
  1. 代理工厂
  • 使用第三方代理对象类调用要代理的对象,执行代理对象的方法其实就是执行被代理对象的方法。(代理对象,被代理对象)
  • 作用:是用来对被代理对象的方法进行增强
  • 手动编写的代理程序 、 JDK动态代理、CGLib动态代理

代理模式注意以下几点:

  • 代理对象的方法与被代理对象的方法声明的时候一致(返回值、参数、方法名)
  • 实际使用的时候调用的是代理对象的方法,其实最终调用的就是被代理对象的方法
  • 在代理对象中,调用被代理对象的方法时候对方法进行增强(扩展)不能减弱。
  • 代理在日常开发中的主要功能:日志记录,异常信息输出
  • 五种增强方式:前置,后置,环绕,最终,异常
    设计原则(单一原则,接口隔离原则,依赖倒转原则...)和设计模式(单例模式,工厂模式...)
  1. 建造者模式(Service三层架构: 控制层,业务层,实际操作层)
    将实例化对象的方式分为了不同的操作
    (1)建造者模式的四个角色
  • Product(产品角色): 一个具体的产品对象。

  • Builder(抽象建造者): 创建一个 Product 对象的各个部件指定的 接口/抽象类。

  • ConcreteBuilder(具体建造者): 实现接口,构建和装配各个部件。

  • Director(指挥者): 构建一个使用 Builder 接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。

  • Javabean实体类:不应该有该类的操作

  • 建造者:操作该Javabean的接口或者抽象类(方法只有定义没有具体执行 )

  • 具体建造者(具体的执行者):操作类/接口 实现类

  • 指挥者:Service 控制层,业务层,实际操作层

  • 主启动类:不与核心对象有直接关系 ,通过指挥者来建立联系
    eg:
    学生管理系统 数组
    StudentBean 实体类
    StudentDao 接口
    StudentDaoImp 实际操作者
    StudentService 指挥者(调用实际操作做)
    StudentTest 主程序 (测试类)
    Student类(实体类)

public class Student {	
	private  String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}

StudentDao类(接口)

public interface StudentDao {	   
	// 查询所有  去数组中查
	Student[] getAllStudent(Student[]  students);
}

StudentDaoImp类

public class StudentDaoImp implements StudentDao {
	@Override
	public Student[] getAllStudent(Student[] students) {
		Student[] stus=new Student[students.length];
		int index=0;
	    // 查询有效数据 
		for (Student student : students) {
			if(student!=null) {
				stus[index]=student;
				System.out.println(student);// 输出语句 
				index++;
			}
		}
		return stus;
	}	
}

StudentService类

public class StudentService  {	
	// 引用接口,合成复用原则     
	private  StudentDao  studentDao;  //引用
	//构造方法  
	public StudentService() {
		super();
		// TODO Auto-generated constructor stub
	}
	public StudentService(StudentDao studentDao) {
		super();
		this.studentDao = studentDao;
	}
	// 业务层调用实际操作层  
	public Student[] getAllStudent(Student[] students) {
		// 实际是使用实际操作类来查询  
		Student[] allStudent = studentDao.getAllStudent(students);
		return allStudent;
	}
}

StudentTest类(测试类)

public class StudentTest {
	public static void main(String[] args) {
		// 容器  
		Student []  students=new Student[3];
		students[0]=new Student("张三",20);
		students[1]=new Student("张三001",21);
    	students[2]=new Student("张三002",22);		
		// 实例化  业务层    需要一个接口对象,使用多态用已知实现子类来做  
		StudentService ss= new StudentService(new StudentDaoImp());
		// 调用 业务层代码 
		ss.getAllStudent(students);
	}
}
  • 建造者模式必须遵守四个对象 实体、接口、实现类、业务类。
  • 代码的扩展和维护方便,接口清楚,对于操作的约束性很高。
  1. 适配器模式:将不符合要求的东西转为符合要求的东西
    (1)适配器模式基本介绍
    适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表 示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作,其别名为包装器(Wrapper)
    适配器模式属于结构型模式
    主要分为三类:类适配器模式、对象适配器模式、接口适配器模式
    (2)适配器模式工作原理
    适配器模式:将一个类的接口转换成另一种接口,让原本接口不兼容的类可以兼容
    从用户的角度看不到被适配者,是解耦的
    用户调用适配器转化出来的目标接口方法,适配器再调用被适配者的相关接口方法
    用户收到反馈结果,感觉只是和目标接口交互
    a.类适配器模式
    Dian220类
public class Dian220 {	
	public  int  outV() {
		return 200;
	}
}

Dian5类

public class Dian5 {	
	//  充电 
	public  void  chongdian() {
		Dian220 d220=new Dian220();
		int outV = d220.outV();
		// 转换  
		if(outV==5) {
			System.out.println("直接充电");
		}else {
			// 对现有电压进行转换
			outV=5;
			if(outV==5) {
				System.out.println("转换后 可以充电了");
			}else {
				System.out.println("电压不对不能充电");
			}
		}		
	}
}

测试类

public class ShiTest {
	
	@Test
	void test() {	
		Dian5 d5=new Dian5();
		d5.chongdian();
	}
}

b.对象适配器
(1) 思路和类的适配器模式相同,只是将 Adapter 类作修改,不是继承 src 类,而是持有 src 类的实例,以解决兼容性的问题。 即:持有 src 类,实现 dst 类接口,完成 src->dst 的适配
(2)根据“合成复用原则”,在系统中尽量使用关联关系(聚合)来替代继承关系。
(3)对象适配器模式是适配器模式常用的一种

  • 使用合成复用原则,将继承去掉,使用类与类的引用。
  • 一个类无法直接使用另外一个类提供的方法,需要一个第三方类来我们将原本不合适的方法进行转换,达到正常使用的效果

本文地址:https://blog.csdn.net/serendipity_xr/article/details/109583665

相关标签: 设计模式 java