目录
什么是设计模式
概览
开闭原则
依赖倒置原则
单一职责原则
接口隔离原则
迪米特原则
里氏替换原则
合成复用原则
设计原则总结
含义:
核心思想:
作用(优点):
实现方式:
实现开闭原则的关键就在于“抽象”。把系统/软件的所有可能的行为抽象成一个抽象底层,这个抽象底层规定出所有的具体实现必须提供的方法的特征。作为系统设计的抽象层,要预见所有可能的扩展,从而使得在任何扩展情况下,系统的抽象底层不需修改;同时,由于可以从抽象底层导出一个或多个新的具体实现,可以改变系统的行为,因此系统设计对扩展是开放的。抽象是对一组事物的通用描述,没有具体的实现,也就表示它可以有非常多的可能性,可以跟随需求的变化而变化。因此,通过接口或抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放,其包含三层含义:
举例说明:
以课程打折为例:
先看课程类接口ICourse:
public interface ICourse {
Integer getId();
String getName();
Double getPrice();
}
public class JavaCourse implements ICourse {
private Integer Id;
private String name;
private Double price;
public JavaCourse(Integer id, String name, Double price) {
this.Id = id;
this.name = name;
this.price = price;
}
public Integer getId() {
return this.Id;
}
public String getName() {
return this.name;
}
public Double getPrice() {
return this.price;
}
}
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
public Double getOriginPrice() {
return super.getPrice();
}
public Double getDiscountPrice() {
return super.getPrice() * 0.61;
}
}
含义:
核心思想:
作用(优点):
实现方式:
举例说明:
以学习多个学科的课程为例
先看XiaoQiang类:
public class XiaoQiang {
public void studyJavaCourse() {
System.out.println("XiaoQiang 在学习 Java 的课程");
}
public void studyPythonCourse() {
System.out.println("XiaoQiang 在学习 Python 的课程");
}
}
来调用一下:
public static void main(String[] args) {
XiaoQiang xq = new XiaoQiang();
xq.studyJavaCourse();
xq.studyPythonCourse();
}
public interface ICourse {
void study();
}
public class JavaCourse implements ICourse {
@Override
public void study() {
System.out.println("XiaoQiang 在学习 Java 课程");
}
}
public class PythonCourse implements ICourse {
@Override
public void study() {
System.out.println("XiaoQiang在学习Python课程");
}
}
修改XiaoQiang类:
public class XiaoQiang {
public void study(ICourse course){
course.study();
}
}
public static void main(String[] args) {
XiaoQiang xq = new XiaoQiang();
xq.study(new JavaCourse());
xq.study(new PythonCourse());
}
public class XiaoQiang {
private ICourse course;
public XiaoQiang(ICourse course){
this.course = course;
}
public void study(){
course.study();
}
}
public static void main(String[] args) {
XiaoQiang tom = new XiaoQiang(new JavaCourse());
xq.study();
}
public class XiaoQiang {
private ICourse course;
public void setCourse(ICourse course) {
this.course = course;
}
public void study() {
course.study();
}
}
public static void main(String[] args) {
XiaoQiang xq = new XiaoQiang();
xq.setCourse(new JavaCourse());
xq.study();
xq.setCourse(new PythonCourse());
xq.study();
}
含义:
核心思想:
作用(优点):
实现方式:
举例说明:
以课程有直播课和录播课。直播课不能快进和快退,录播可以可以任意的反复观看,功能职责不一样为例说明。
public class Course {
public void study(String courseName) {
if ("直播课".equals(courseName)) {
System.out.println("不能快进");
} else {
System.out.println("可以任意的来回播放");
}
}
}
public static void main(String[] args) {
Course course = new Course();
course.study("直播课");
course.study("录播课");
}
public class LiveCourse {
public void study(String courseName) {
System.out.println(courseName + "不能快进看");
}
}
public class ReplayCourse {
public void study(String courseName) {
System.out.println("可以任意的来回播放");
}
}
public static void main(String[] args) {
LiveCourse liveCourse = new LiveCourse();
liveCourse.study("直播课");
ReplayCourse replayCourse = new ReplayCourse();
replayCourse.study("录播课");
}
public interface ICourse {
//获得基本信息
String getCourseName();
//获得视频流
byte[] getCourseVideo();
//学习课程
void studyCourse();
//退款
void refundCourse();
}
public interface ICourseInfo {
String getCourseName();
byte[] getCourseVideo();
}
ICourseManager 接口:
public interface ICourseManager {
void studyCourse();
void refundCourse();
}
来看一下类图:
private void modifyUserInfo(String userName,String address){
userName = "XiaoQiang";
address = "Changsha";
}
private void modifyUserInfo(String userName,String address,boolean bool){
if(bool){
userName = "XiaoQiang";
}else{
address = "Changsha";
}
}
private void modifyUserName(String userName){
userName = "XiaoQiang";
}
private void modifyAddress(String address){
address = "Changsha";
}
这修改之后,开发起来简单,维护起来也容易。所以编写代码的过程,尽可能地让接口和方法保持单一职责,便于我们项目后期的维护
含义:
核心思想
作用(优点):
接口隔离原则跟单一职责原则区别:
实现方式:
举例说明:
public interface IAnimal {
void eat();
void fly();
void swim();
}
public class Bird implements IAnimal {
@Override
public void eat() {
}
@Override
public void fly() {
}
@Override
public void swim() {
}
}
Dog 类实现:
public class Dog implements IAnimal {
@Override
public void eat() {
}
@Override
public void fly() {
}
@Override
public void swim() {
}
}
public interface IEatAnimal {
void eat();
}
IFlyAnimal 接口:
public interface IFlyAnimal {
void fly();
}
ISwimAnimal 接口:
public interface ISwimAnimal {
void swim();
}
含义:
核心思想
作用(优点):
举例说明:
public class Course {
}
public class TeamLeader {
public void checkNumberOfCourses(List courseList) {
System.out.println("目前已发布的课程数量是:" + courseList.size());
}
}
Boss 类:
public class Boss {
public void commandCheckNumber(TeamLeader teamLeader){
//模拟 Boss 一页一页往下翻页,TeamLeader 实时统计
List courseList = new ArrayList();
for (int i= 0; i < 20 ;i ++) {
courseList.add(new Course());
}
teamLeader.checkNumberOfCourses(courseList);
}
}
public class TeamLeader {
public void checkNumberOfCourses() {
List courseList = new ArrayList();
for (int i = 0; i < 20; i++) {
courseList.add(new Course());
}
System.out.println("目前已发布的课程数量是:"+courseList.size());
}
}
含义:
核心思想:
作用(优点):
举例说明:
public class Rectangle {
private long height;
private long width;
@Override
public long getWidth() {
return width;
}
@Override
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
public void setWidth(long width) {
this.width = width;
}
}
public class Square extends Rectangle {
private long length;
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
@Override
public long getWidth() {
return getLength();
}
@Override
public long getHeight() {
return getLength();
}
@Override
public void setHeight(long height) {
setLength(height);
}
@Override
public void setWidth(long width) {
setLength(width);
}
}
public static void resize(Rectangle rectangle){
while (rectangle.getWidth() >= rectangle.getHeight()){
rectangle.setHeight(rectangle.getHeight() + 1);
System.out.println("width:"+rectangle.getWidth() + ",height:"+rectangle.getHeight());
}
System.out.println("resize 方法结束" + "\nwidth:"+rectangle.getWidth() + ",height:"+rectangle.getHeight());
}
public static void main(String[] args) {
Rectangle rectangle = new Rectangle();
rectangle.setWidth(20);
rectangle.setHeight(10);
resize(rectangle);
}
运行结果:
width:20,height:11
width:20,height:12
width:20,height:13
width:20,height:14
width:20,height:15
width:20,height:16
width:20,height:17
width:20,height:18
width:20,height:19
width:20,height:20
width:20,height:21
resize 方法结束
width:20,height:21
public static void main(String[] args) {
Square square = new Square();
square.setLength(10);
resize(rectangle);
}
public interface Quadrangle {
long getWidth();
long getHeight();
}
public class Rectangle implements Quadrangle {
private long height;
private long width;
@Override
public long getWidth() {
return width;
}
public long getHeight() {
return height;
}
public void setHeight(long height) {
this.height = height;
}
public void setWidth(long width) {
this.width = width;
}
}
public class Square implements Quadrangle {
private long length;
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
@Override
public long getWidth() {
return length;
}
@Override
public long getHeight() {
return length;
}
}
此时,如果我们把 resize()方法的参数换成四边形 Quadrangle 类,方法内部就会报错。 因为正方形 Square 已经没有了 setWidth()和 setHeight()方法了。因此,为了约束继承泛滥,resize()的方法参数只能用 Rectangle 长方形。
含义:
核心思想:
实现方式:
聚合与组合的区别:
复用的基本方式有两种:
复用两种方式的区别:
举例说明:
以数据库操作为例,先来创建 DBConnection 类:
public class DBConnection {
public String getConnection() {
return "MySQL 数据库连接";
}
}
public class ProductDao {
private DBConnection dbConnection;
public void setDbConnection(DBConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void addProduct() {
String conn = dbConnection.getConnection();
System.out.println("使用" + conn + "增加产品");
}
}
public abstract class DBConnection {
public abstract String getConnection();
}
public class MySQLConnection extends DBConnection {
@Override
public String getConnection() {
return "MySQL 数据库连接";
}
}
再创建 Oracle 支持的逻辑:
public class OracleConnection extends DBConnection {
@Override
public String getConnection() {
return "Oracle 数据库连接";
}
}
这7种设计原则是软件设计模式必须尽量遵循的原则,各种原则要求的侧重点不同: