首页 > 其他 > 详细

设计模式简介(一)

时间:2021-04-28 16:36:22      阅读:30      评论:0      收藏:0      [点我收藏+]

设计模式的定义

? 软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。

设计模式重要性

? 1、设计模式为程序提供可拓展性。

? 2、遵循设计模式可以为程序提供维修性,可读性,规范性。

? 3、 面试问题

? 4、设计模式无处不在

? 5、成为优秀程序员必备条件。

设计模式的目的

? 设计模式是为了让程序,具有更好的:代码复用性可读性(规范性),可拓展性可靠性使程序呈现高内聚,低耦合的特性

设计模式七大原则

1、单一职责

定义

? 一个类应该只负责一项职责

注意事项和细节

? 1、降低类的复杂度,一个类只负责一项原则

? 2、提高类的可读性,可维护性。

? 3、降低变更引起的风险。

? 4、通常情况下,应当遵守单一职责原则。只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则。

2、接口隔离

定义

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

解释

技术分享图片

? 1)类a通过接口 interface 1依赖b,类c通过接口 interface 1 依赖d,如果接口 interface 对于a 和c来说不是最小接口,那么类b和类d必须去实现他们不需要的方法。

? 2)将接口interface 1拆分为独立的几个接口,类a和类c分别为与他们需要的接口建立依赖关系,也就是采用接口隔离原则。

? 3)接口interface 1 中出现的方法,根据实际情况拆分为三个接口。

? 技术分享图片

3、依赖倒置

定义

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

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

3)依赖倒转(倒置)的中心思想是面向接口编程

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

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

应用实例

package com.itsmallstudent.principle.inversion;

public class DependencyInversion {
	
	public static void main(String[] args) {
		Person person  = new Person();
		person.receive(new Email());
		
	}

}
class Email{
	public String getInfo(){
		return "hello world";
	}
}

/**
 * 1,完成了Person接受消息的功能
 * 方式1分析
 * 1.简单,比较容易想到
 * 2.如果获取对象是微信等新增类,那么person类需要新增对应方法
 * @author cpms
 *
 */
class Person{
	public void receive(Email email){
		System.out.println(email.getInfo());
	}
}


//使用依赖倒转原则
package com.itsmallstudent.principle.inversion;

public class DependencyInversion2 {
	public static void main(String[] args) {
		Person2 person = new Person2();
		person.receive(new Phone());
		person.receive(new WeChat());
		System.out.println();
	}
}

interface Msg{
	String getInfo();
}


class Phone implements Msg{

	@Override
	public String getInfo() {
		// TODO Auto-generated method stub
		return "手机短信:Hello World";
	}
	
}

class WeChat implements Msg{

	@Override
	public String getInfo() {
		// TODO Auto-generated method stub
		return "微信消息:Hello World";
	}
	
}

class Person2{
	public void receive(Msg msg){
		System.out.println(msg.getInfo());
	}
}

依赖关系传递的三种方式和案例

1)接口传递
interface Msg{
	String getInfo();
}
interface Receicve{
    String Receice(Msg msg);
}
class Person3 implements Receicve{
	@Override
	public String Receice(Msg msg) {
		// TODO Auto-generated method stub
		return msg.getInfo();
	}
	
}
2)构造方法传递,setter方法传递
interface Msg{
	String getInfo();
}
interface Receicve{
    String Receice();
}

class Person3 implements Receicve{
	
	private Msg yourMsg;
    
    //构造方法
    public Person3(Msg msg){
		this.yourMsg=msg;
	}
	
	public Msg getYourMsg() {
		return yourMsg;
	}

    //setter 方法
	public void setYourMsg(Msg yourMsg) {
		this.yourMsg = yourMsg;
	}

	@Override
	public String Receice() {
		// TODO Auto-generated method stub
		return yourMsg.getInfo();
	}
	
}

注意事项和细节

  1. 低层模块尽量都要有抽象类和接口,或者两者都有,程序的稳定性更好
  2. 变量的声明类型尽量是抽象类和接口,这样对我们的变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化。
  3. 继承时遵循里氏替换原则。

4、里氏替换原则

基本介绍

  1. 如果对每个类型为T1的对象O1,都有类型为T2的对象O2,使得以T1定义的所有程序p在所有的对象O1都代换成O2时,程序p的行为没有变化,那么类型T2是类型T1的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象。
  2. 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法。
  3. 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖来处理问题。
//创建一个更加基础的基类
class Basic{
	//把更加基础的方法和成员写到basic中

}
//A类
class A extends Basic {
	public int function1(int a,int b){
		return a-b;
	}
}
//B类
class B extends Basic{
	//如果b想使用a的方法,使用组合关系
	private A a = new A();
	
	public int function1(int a, int b) {
		// TODO Auto-generated method stub
		return a+b;
	}
	
	public int function2(int a,int b){
		return function1(a, b)+9;
	}
	//假如我们仍然想使用A的方法
	public int function3(int a,int b){
		return this.a.function1(a, b);
	}
	
}

5、开闭原则

基本介绍

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

代码

package com.itsmallstudent.principle.ocp;

/**
 * 优点是比较好理解,简单易操作
 * 缺点是违反了设计模式的ocp原则,则对扩展开放,对修改关闭,即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码
 * 比如我们这时要新增加一个图形种类,我们需要做如下修改,修改的地方比较多
 * @author cpms
 *
 */
public class Example {
	
	public static void main(String[] args) {
		//使用看看存在的问题
		GraphicEditor graphicEditor =  new GraphicEditor();
		graphicEditor.drawRectangle(new Rectangle());
		graphicEditor.drawCircle(new Circle());
	}

}

//这是一个用于绘图的类
class GraphicEditor{
	//接受shape对象
	public void drawShape(Shape s){
		if(s.my_type==1){
			drawRectangle(s);
		}else if(s.my_type==2) {
			drawCircle(s);
		}
	}
	//绘制矩形
	public void drawRectangle(Shape r){
		System.out.println("绘制矩形");
	}
	//绘制圆形
	public void drawCircle(Shape r){
		System.out.println("绘制圆形");
	}
}

class Shape{
	int my_type;
}

class Rectangle extends Shape{
	Rectangle() {
		super.my_type=1;
	}
}

class Circle extends Shape{
	public Circle() {
		super.my_type=2;
	}
}

改进的思路分析

? 思路:把创建Shape类做成抽象类,并提供一个抽象的draw方法,让子类去实现即可,这样我们有新的图形种类时,只需要让新的图形类继承Shape,并实现draw方法即可,

//这是一个用于绘图的类
class GraphicEditor1{
	//接受shape对象
	public void drawShape(Shape1 e){
		e.darw();
	}
	
}
abstract class Shape1{
	int my_type;
	abstract void  darw();
}
class Rectangle2 extends Shape1{
	public Rectangle2() {
		// TODO Auto-generated constructor stub
		super.my_type=1;
	}
	@Override
	void darw() {
		// TODO Auto-generated method stub
		System.out.println("绘制矩形");
	}
}

class Circle2 extends Shape1{
	public Circle2() {
		// TODO Auto-generated constructor stub
		super.my_type=2;
	}
	@Override
	void darw() {
		// TODO Auto-generated method stub
		System.out.println("绘制圆形");
	}
	
}

6、迪米特原则

基本介绍

  1. 一个对象应该对其他对象保持最小的了解
  2. 类与类关系越密切,耦合度越大,
  3. 迪米特法则又叫最少知道原则,即一个类对自己依赖的类知道的越少越好,也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的pulic 方法,不对外暴露任何信息。
  4. 迪米特法则还有一个更简单的定义,只与直接的朋友通信。
  5. 直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这个两个对象之间是朋友关系。耦合的方法很多。依赖,关联,组合,聚合等,其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现再局部变量的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。

代码

package com.itsamllstudent.principle.demeter;
import java.util.ArrayList;
import java.util.List;
public class Demeter1 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//创建了一个SchoolManager对象
		SchoolManager schoolManager = new SchoolManager();
		//
		schoolManager.printAllEmployee(new CollegeManager());
	}
}
//学校总部员工
class Employee{
	private String id;
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

}
//学院员工
class CollegeEmployee{
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	private String id;
	
}
//管理学院员工的管理类
class CollegeManager{
	public List<CollegeEmployee> getAllEmployees(){
		List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
		for (int i = 0; i < 10; i++) {
			CollegeEmployee employee = new CollegeEmployee();
			employee.setId("学院员工id为"+i);
			list.add(employee);
		}
		return list;
	}
}
//学校的管理类
// 分析SchoolManger 类的直接朋友类有哪些,Employee,CollegeManager
// CollegeEmployee不是直接朋友,而是一个陌生类,这样违背了迪米特法则。
class SchoolManager{
	public List<Employee> getAllEmployees(){
		List<Employee> list = new ArrayList<Employee>();
		for (int i = 0; i < 10; i++) {
			Employee employee = new Employee();
			employee.setId("学院总部员工id为"+i);
			list.add(employee);
		}
		return list;
	}
	//分析问题
	//1.CollegeEmployee不是SchoolManager的直接朋友
	//2.CollegeEmployee是以局部变量方法出现在SchoolManager
	//3.违反了迪米特法则
	void printAllEmployee(CollegeManager sub){
		List<CollegeEmployee> list = sub.getAllEmployees();
		System.out.println("-----------分公司员工----------------");
		for (CollegeEmployee e : list) {
			System.out.println(e.getId());
		}
		List<Employee> list2 = this.getAllEmployees();
		System.out.println("-----------学校总部员工------------------");
		for (Employee employee : list2) {
			System.out.println(employee.getId());
		}
	}
	
}
  1. 迪米特法则的核心是降低类之间的耦合
  2. 但是注意,由于每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类间(对象间)耦合关系,并不是要求完全没有依赖关系

改进如下

package com.itsamllstudent.principle.demeter.improve;

import java.util.ArrayList;
import java.util.List;
public class ImproveDemeter1 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//创建了一个SchoolManager对象
		SchoolManager schoolManager = new SchoolManager();
		//输出
		schoolManager.printAllEmployee(new CollegeManager());
	}

}
//学校总部员工
class Employee{
	private String id;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}

}
//学院员工
class CollegeEmployee{
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	private String id;
	
}
//管理学院员工的管理类
class CollegeManager{
	public List<CollegeEmployee> getAllEmployees(){
		List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
		for (int i = 0; i < 10; i++) {
			CollegeEmployee employee = new CollegeEmployee();
			employee.setId("学院员工id为"+i);
			list.add(employee);
		}
		return list;
	}
	//输出学院员工的信息
	public void printEmployee() {
		List<CollegeEmployee> list = this.getAllEmployees();
		System.out.println("-----------分公司员工----------------");
		for (CollegeEmployee e : list) {
			System.out.println(e.getId());
		}
	}
}
//学校的管理类
class SchoolManager{
	//
	public List<Employee> getAllEmployees(){
		List<Employee> list = new ArrayList<Employee>();
		for (int i = 0; i < 10; i++) {
			Employee employee = new Employee();
			employee.setId("学院总部员工id为"+i);
			list.add(employee);
		}
		return list;
	}
	void printAllEmployee(CollegeManager sub){
		sub.printEmployee();
		List<Employee> list2 = this.getAllEmployees();
		System.out.println("-----------学校总部员工------------------");
		for (Employee employee : list2) {
			System.out.println(employee.getId());
		}
	}
	
	
}

7、合成复用原则

基本介绍

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

技术分享图片

设计原则核心思想

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

设计模式简介(一)

原文:https://www.cnblogs.com/It-smallstudent/p/14714216.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!