文章目录
前言
代码部分为网络上收集,并根据自己的理解记忆
什么是GOF
在 1994 年, 由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了名为Design Patterns - Elements of Rausable Object-Oriented Software(中文译名:设计模式-可复用的面对对象软件元素)的书,该书首次提到了软件开发中设计模式的概念。
对接口编程而不是对实现编程。
优先使用对象组合而不是继承。
设计模式的基石
- 封装
- 继承
- 多态
- 顺序
- 判断
- 循环
组件的生命周期
设计模式的7大原则
开闭原则
- 软件实体应当对扩展开放,对修改关闭
- 合成复用原则、里氏替换原则相辅相成,都是开闭原则的具体实现规范。
- 人话:扩展新类而不是修改旧类。
里氏替换原则
- 继承必须确保超类所拥有的性质在子类中仍然成立。
- 人话:继承父类而不去改变父类。
依赖倒置原则
- 高层模块不应该依赖底层模块,两者都是应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象
- 人话:面向接口编程,而不是面向实现类
单一职责原则
- 一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分
- 人话:每个类只负责自己的事情,而不是变成万能
接口隔离原则
- 一个类对另一个类的依赖应该建立在最小的接口上
- 人话:各个类建立自己的专用接口,而不是建立万能接口
迪米特法则
- 最少知道原则
- 只与你的直接朋友交谈,不跟 ‘陌生人’ 说话
- 人话:无需直接交互的两个类,如果需要交互,使用中间者
- 警:过度使用迪米特法则则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低
合成复用原则
- 又叫组合/聚合复用原则
- 软件服用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现
- 人言:优先组合其次继承
代码
开闭原则
扩展新类而不是修改旧类
场景秒速,假设:某教学网站上,出售一个价格888的教学课程,而这个时候做活动,需要将这个课程打折出售,是直接修改呢,还是扩展它呢
// 课程
public interface ICourse {
Integer getId();
String getName();
Double getPrice();
}
// java课程
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;}
}
// 打折后的Java课程
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
public Double getDiscountPrice(){
return super.getPrice()*0.8;
}
}
// 测试
public class Test {
public static void main(String[] args) {
ICourse iCourse = new JavaDiscountCourse(96, "Java从零到企业级电商开发", 348d);
JavaDiscountCourse javaCourse = (JavaDiscountCourse) iCourse;
System.out.println(
"课程ID:" + javaCourse.getId() +
" 课程名称:" + javaCourse.getName() +
" 课程原价:" + javaCourse.getPrice() +
" 课程折后价格:" + javaCourse.getDiscountPrice() + "元");
}
}
里氏替换原则
继承父类而不去改变父类
方法的输入和输出
methodinput
public class Base {
public void method(HashMap map){
System.out.println("父类被执行");
}
}
public class Child extends Base {
// @Override
// public void method(HashMap map) {
// System.out.println("子类HashMap入参方法被执行");
// }
public void method(Map map) {
System.out.println("子类HashMap入参方法被执行");
}
}
public class Test {
public static void main(String[] args) {
Base child = new Child();
HashMap hashMap = new HashMap();
child.method(hashMap);
}
}
// 输出:父类被执行
methodoutput
public abstract class Base {
public abstract Map method();
}
public class Child extends Base {
@Override
public HashMap method() {
HashMap hashMap = new HashMap();
System.out.println("子类method被执行");
hashMap.put("message","子类method被执行");
return hashMap;
}
}
public class Test {
public static void main(String[] args) {
Child child = new Child();
System.out.println(child.method());
}
}
// 四边形
public interface Quadrangle {
long getWidth();
long getLength();
}
// 长方形属于四边形一种
public class Rectangle implements Quadrangle {
private long length;
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 Test {
public static void resize(Rectangle rectangle){
while (rectangle.getWidth() <= rectangle.getLength()){
rectangle.setWidth(rectangle.getWidth()+1);
System.out.println("width:"+rectangle.getWidth() + " length:"+rectangle.getLength());
}
System.out.println("resize方法结束 width:"+rectangle.getWidth() + " length:"+rectangle.getLength());
}
public static void main(String[] args) {
Rectangle rectangle = new Rectangle();
rectangle.setWidth(10);
rectangle.setLength(20);
resize(rectangle);
}
}
接口隔离原则
各个类建立自己的专用接口,而不是建立万能接口
场景:
不同动物会的不一样
鸟:吃、飞、游
狗:吃、游
public class Bird implements IAnimalAction {
@Override
public void eat() {}
@Override
public void fly() {}
@Override
public void swim() {}
}
public class Dog implements ISwimAnimalAction,IEatAnimalAction {
@Override
public void eat() {}
@Override
public void swim() {}
}
// 吃、飞、游都会
public interface IAnimalAction {
void eat();
void fly();
void swim();
}
// 吃
public interface IEatAnimalAction {
void eat();
}
// 飞行
public interface IFlyAnimalAction {
void fly();
}
// 游泳
public interface ISwimAnimalAction {
void swim();
}
合成复用原则
优先组合其次继承
场景描述:往不同的数据库中,添加商品数据。
public abstract class DBConnection {
public abstract String getConnection();
}
public class MySQLConnection extends DBConnection{
@Override
public String getConnection() {
return "MySQL数据库链接";
}
}
public class PostgreSQLConnection extends DBConnection{
@Override
public String getConnection() {
return "PostgreSQL数据库连接";
}
}
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 class Test {
public static void main(String[] args) {
ProductDao productDao = new ProductDao();
productDao.setDbConnection(new PostgreSQLConnection());
productDao.addProduct();
}
}
迪米特原则
无需要直接交互的两个类,如果需要交互,使用中间者
场景描述:培训公司有很多课程,该公司老板想确认有多少课程,这时候需要一个中间者(管理者)告诉他,而不是他直接确认
public class Boss {
public void commandCheckNumber(TeamLeader teamLeader){
teamLeader.checkNumberOfCourses();
}
}
public class Course {
}
public class TeamLeader {
public void checkNumberOfCourses(){
List<Course> courseList = new ArrayList<Course>();
for(int i = 0 ;i < 20;i++){
courseList.add(new Course());
}
System.out.println("在线课程的数量是:"+courseList.size());
}
}
public class Test {
public static void main(String[] args) {
Boss boss = new Boss();
TeamLeader teamLeader = new TeamLeader();
boss.commandCheckNumber(teamLeader);
}
}
依赖倒置原则
面向接口编程,而不是实现类
public class FECourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("Geely在学习FE课程");
}
}
public class Geely {
public void setiCourse(ICourse iCourse) {
this.iCourse = iCourse;
}
private ICourse iCourse;
public void studyImoocCourse(){
iCourse.studyCourse();
}
}
public interface ICourse {
void studyCourse();
}
public class JavaCourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("Geely在学习Java课程");
}
}
public class PythonCourse implements ICourse {
@Override
public void studyCourse() {
System.out.println("Geely在学习Python课程");
}
}
public class Test {
//v1
// public static void main(String[] args) {
// Geely geely = new Geely();
// geely.studyJavaCourse();
// geely.studyFECourse();
// }
//v2
// public static void main(String[] args) {
// Geely geely = new Geely();
// geely.studyImoocCourse(new JavaCourse());
// geely.studyImoocCourse(new FECourse());
// geely.studyImoocCourse(new PythonCourse());
// }
//v3
// public static void main(String[] args) {
// Geely geely = new Geely(new JavaCourse());
// geely.studyImoocCourse();
// }
public static void main(String[] args) {
Geely geely = new Geely();
geely.setiCourse(new JavaCourse());
geely.studyImoocCourse();
// geely.setiCourse(new FECourse());
// geely.studyImoocCourse();
}
}
单一职责原则
每个类只负责自己的事情,而不是编程万能
public class FlyBird {
public void mainMoveMode(String birdName){
System.out.println(birdName+"用翅膀飞");
}
}
public class WalkBird {
public void mainMoveMode(String birdName){
System.out.println(birdName+"用脚走");
}
}
// 错误例子
public class Bird {
public void mainMoveMode(String birdName){
if("鸵鸟".equals(birdName)){
System.out.println(birdName+"用脚走");
}else{
System.out.println(birdName+"用翅膀飞");
}
}
}
public class Test {
public static void main(String[] args) {
// Bird bird = new Bird();
// bird.mainMoveMode("大雁");
// bird.mainMoveMode("鸵鸟");
FlyBird flyBird = new FlyBird();
flyBird.mainMoveMode("大雁");
WalkBird walkBird = new WalkBird();
walkBird.mainMoveMode("鸵鸟");
}
}