最全23种设计模式详解(一)

本博客文章(学习笔记)导航 (点击这里访问)

一、UML

1.1 UML的定义

UML:统一建模语言(Unified Modeling Language,UML)是一种为面向对象系统的产品进行说明、可视化和编制文档的一种标准语言,是非专利的第三代建模和规约语言。UML是面向对象设计的建模工具,独立于任何具体程序设计语言。

1.2 UML的作用

(1)为软件系统建立可视化模型。
UML符号具有良好的语义,不会引起歧义;基于UML的可视化模型,使系统结构直观、易于理解;使用UML进行软件系统的模型不但有利于系统开发人员和系统用户的交流,还有利于系统维护。模型是系统的蓝图,它可以对开发人员的规划进行补充,模型可以帮助开发人员规划要建的系统。有了正确的模型就可以实现正确的系统设计,保证用户的要求得到满足,系统能在需求改变时站得住脚。对于一个软件系统,模型就是开发人员为系统设计的一组视图。这组视图不仅描述了用户需要的功能,还描述了怎样去实现这些功能。

(2)为软件系统建立构件。
UML不是面向对象的编程语言,但它的模型可以直接对应到各种各样的编程语言。例如,它可以使用代码生成器工具将UML模型转换为多种程序设计语言代码,如可生成C++XML,DTD,JAVAVisual basic等语言的代码,或使用反向生成器工具将程序源代码转换为UML;甚至还可以生成关系数据库中的表。

(3)为软件系统建立文档。
UML可以为系统的体系结构及其所有细节建立文档。不同的UML模型图可以作为项目不同阶段的软件开发文档。

1.3 UML的分类

UML2.2中一共定义了14种图示,分类如下:
结构式图形:强调的是系统式的建模
行为式图形:强调系统模型中的触发事件
交互式图形:属于行为式图形子集,强调系统模型种的资料流程

1.3.1 静态图

静态图(类图,对象图,包图)
实现图(组件图,部署图)
剖面图
复合结构图

1.3.2 行为式图形

活动图
状态图
用例图

1.3.3 交互式图形

通信图
交互概述图
时序图
时间图

1.4 UML类图

Class Diagram:用于表示类、接口、实例之间相互静态关系

常见的符号含义

1 UML箭头方向:从子类指向父类(只有知道对方信息时才能指向对方)
2 实线:代表继承了父类(关联关系)
3 虚线:代表实现了一个接口(依赖关系)
4 空心菱形:聚合关系
5 实心菱形:组合关系

常见的数字表达及含义

假设A类和B类,数字标记在A类侧
0…1 : 0或1个实例
0…: 0或多个实例
1…1: 1个实例
1 : 只能有一个实例
1…
: 至少有一个实例

1.5 UML时序图

Sequence Diagram:是显示对象之间交互的图,这些对象是按时间顺序排列的
时序图中包括的建模元素主要有:对象(Actor)、生命线(Lifeline)、控制焦点(Focus of control)、消息(message)、同步调用、异步调用

image.png

1.6 类的表示

一个正常的类

line 1 GeelyClass :一个正常的类

属性

line 2 + 表示public权限 :String 代表类型
line 3 - 表示private权限
line 4 # 表示protected权限
line 5 ~ 表示default权限
line 6 下划线代表静态属性(同理方法代表静态方法)

行为

+study( ) : 斜体代表抽象方法
+openMac( ) : boolean 表示返回值boolean类型

image.png

1.7 UML类关系图

类关系图来自大话设计模式

image.png

二、设计原则

2.1 七大设计原则

1 开闭原则
2 依赖倒置原则
3 单一职责原则
4 接口隔离原则
5 迪米特法则(最少知道原则)
6 里氏替换原则
7 合成复原原则

在系统的设计过程中也不是完全遵守七大原则,需要做相应的取舍,讲究一个度,一个平衡。

2.2 开闭原则

image.png

类图
image.png

实例代码

package com.geely.design.principle.openclose;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/7
 */
public interface ICourse {
    Integer getId();
    String getName();
    Double getPrice();
}

package com.geely.design.principle.openclose;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/7
 */
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;
    }

}

package com.geely.design.principle.openclose;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 扩展而不修改
 * @Date 2022/4/7
 */
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;
    }
}


package com.geely.design.principle.openclose;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe
 * @Date 2022/4/7
 */
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() + "元");
    }
}

2.3 依赖倒置原则

image.png

类图
image.png
代码实现

package com.geely.design.principle.dependenceinversion;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/7
 */
public interface ICourse {
    void studyCourse();
}

package com.geely.design.principle.dependenceinversion;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/7
 */
public class FECourse implements ICourse {
    @Override
    public void studyCourse() {
        System.out.println("Geely在学习FE课程");
    }

}

package com.geely.design.principle.dependenceinversion;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/7
 */
public class JavaCourse implements ICourse {

    @Override
    public void studyCourse() {
        System.out.println("Geely在学习Java课程");
    }
}

package com.geely.design.principle.dependenceinversion;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/7
 */
public class PythonCourse implements ICourse {
    @Override
    public void studyCourse() {
        System.out.println("Geely在学习Python课程");
    }
}

package com.geely.design.principle.dependenceinversion;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/7
 */
public class Geely {

    public void setiCourse(ICourse iCourse) {
        this.iCourse = iCourse;
    }

    private ICourse iCourse;



    public void studyImoocCourse(){
        iCourse.studyCourse();
    }

}

package com.geely.design.principle.dependenceinversion;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/7
 */
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();

    }


}

2.4 单一职责原则

image.png

类图
image.png

代码实现

package com.geely.design.principle.singleresponsibility;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Bird {
    public void mainMoveMode(String birdName){
        if("鸵鸟".equals(birdName)){
            System.out.println(birdName+"用脚走");
        }else{
            System.out.println(birdName+"用翅膀飞");
        }
    }
}

package com.geely.design.principle.singleresponsibility;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class WalkBird {
    public void mainMoveMode(String birdName){
        System.out.println(birdName+"用脚走");
    }
}

package com.geely.design.principle.singleresponsibility;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class FlyBird {
    public void mainMoveMode(String birdName){
        System.out.println(birdName+"用翅膀飞");
    }
}

package com.geely.design.principle.singleresponsibility;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
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("鸵鸟");

    }
}

课程类图
image.png
代码

package com.geely.design.principle.singleresponsibility;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public interface ICourseManager {
    void studyCourse();
    void refundCourse();
}

package com.geely.design.principle.singleresponsibility;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public interface ICourseContent {
    String getCourseName();
    byte[] getCourseVideo();
}

package com.geely.design.principle.singleresponsibility;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class CourseImpl implements ICourseManager,ICourseContent {
    @Override
    public void studyCourse() {

    }

    @Override
    public void refundCourse() {

    }

    @Override
    public String getCourseName() {
        return null;
    }

    @Override
    public byte[] getCourseVideo() {
        return new byte[0];
    }
}

package com.geely.design.principle.singleresponsibility;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Method {
    private void updateUserInfo(String userName,String address){
        userName = "geely";
        address = "beijing";
    }

    private void updateUserInfo(String userName,String... properties){
        userName = "geely";
//        address = "beijing";
    }

    private void updateUsername(String userName){
        userName = "geely";
    }
    private void updateUserAddress(String address){
        address = "beijing";
    }

    private void updateUserInfo(String userName,String address,boolean bool){
        if(bool){
            //todo something1
        }else{
            //todo something2
        }
        userName = "geely";
        address = "beijing";
    }

}

2.5 接口隔离原则

单一职责针对的是类
接口隔离针对的是接口
image.png

类图
image.png

代码

package com.geely.design.principle.interfacesegregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe
 * @Date 2022/4/8
 */
public interface IAnimalAction {
    void eat();
    void fly();
    void swim();

}

package com.geely.design.principle.interfacesegregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Bird implements IAnimalAction {
    @Override
    public void eat() {

    }

    @Override
    public void fly() {

    }

    @Override
    public void swim() {

    }
}

package com.geely.design.principle.interfacesegregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public interface IEatAnimalAction {
    void eat();
}

package com.geely.design.principle.interfacesegregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe
 * @Date 2022/4/8
 */
public interface IFlyAnimalAction {
    void fly();
}

package com.geely.design.principle.interfacesegregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe
 * @Date 2022/4/8
 */
public interface ISwimAnimalAction {
    void swim();
}

package com.geely.design.principle.interfacesegregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Dog implements ISwimAnimalAction,IEatAnimalAction {

    @Override
    public void eat() {

    }

    @Override
    public void swim() {

    }
}

2.6 迪米特原则

最少知道原则
image.png

image.png

类图

image.png

代码

package com.geely.design.principle.demeter;


/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Boss {

    public void commandCheckNumber(TeamLeader teamLeader){
        teamLeader.checkNumberOfCourses();
    }

}
package com.geely.design.principle.demeter;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
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());
    }

}

package com.geely.design.principle.demeter;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Course {
}

package com.geely.design.principle.demeter;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Test {
    public static void main(String[] args) {
        Boss boss = new Boss();
        TeamLeader teamLeader = new TeamLeader();
        boss.commandCheckNumber(teamLeader);

    }
}

输出

在线课程的数量是:20

Process finished with exit code 0

2.7 里氏替换原则

image.png

image.png
image.png
类图
image.png
代码

package com.geely.design.principle.liskovsubstitution;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public interface Quadrangle {
    long getWidth();
    long getLength();

}

package com.geely.design.principle.liskovsubstitution;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
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;
    }
}

package com.geely.design.principle.liskovsubstitution;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Square implements Quadrangle {
    private long sideLength;

    public long getSideLength() {
        return sideLength;
    }

    public void setSideLength(long sideLength) {
        this.sideLength = sideLength;
    }

    @Override
    public long getWidth() {
        return sideLength;
    }

    @Override
    public long getLength() {
        return sideLength;
    }
}

package com.geely.design.principle.liskovsubstitution;
/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
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 static void main(String[] args) {
        Square square = new Square();
//        square.setLength(10);
//        resize(square);
    }
}

2.8 合成复用原则

image.png

类图
image.png
代码

package com.geely.design.principle.compositionaggregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public abstract class DBConnection {
//    public String getConnection(){
//        return "MySQL数据库连接";
//    }
    public abstract String getConnection();
}

package com.geely.design.principle.compositionaggregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class MySQLConnection extends DBConnection {
    @Override
    public String getConnection() {
        return "MySQL数据库连接";
    }
}

package com.geely.design.principle.compositionaggregation;
/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class PostgreSQLConnection extends DBConnection {
    @Override
    public String getConnection() {
        return "PostgreSQL数据库连接";
    }
}

package com.geely.design.principle.compositionaggregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
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+"增加产品");
    }
}

package com.geely.design.principle.compositionaggregation;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Test {
    public static void main(String[] args) {
        ProductDao productDao = new ProductDao();
        productDao.setDbConnection(new PostgreSQLConnection());
        productDao.addProduct();
    }
}

三、简单工厂

3.1 定义

简单工厂定义:由一个工厂对象决定创建出哪一种产品的实例

类型:创建型 但不属于23种之中

使用场景:
1 工厂类负责创建的对象比较少
2 客户端只知道传入工厂类的参数,对于如何创建对象的(逻辑)不关心

优点: 只需要传入一个正确的参数,就可以获取到要获取的对象,无须知道创建细节

缺点:新增产品需要修改工厂类的判断逻辑,违背了开闭原则

3.2 类图

image.png

3.3 简单工厂代码

package com.geely.design.pattern.creational.simplefactory;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public abstract class Video {
    public abstract void produce();

}

package com.geely.design.pattern.creational.simplefactory;
/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class JavaVideo extends Video {
    @Override
    public void produce() {
        System.out.println("录制Java课程视频");
    }
}

package com.geely.design.pattern.creational.simplefactory;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class PythonVideo extends Video {
    @Override
    public void produce() {
        System.out.println("录制Python课程视频");
    }
}

package com.geely.design.pattern.creational.simplefactory;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class VideoFactory {
    public Video getVideo(Class c){
        Video video = null;
        try {
            video = (Video) Class.forName(c.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return video;
    }


    public Video getVideo(String type){
        if("java".equalsIgnoreCase(type)){
            return new JavaVideo();
        }else if("python".equalsIgnoreCase(type)){
            return new PythonVideo();
        }
        return null;
    }

}

package com.geely.design.pattern.creational.simplefactory;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/8
 */
public class Test {
    public static void main(String[] args) {
//        VideoFactory videoFactory = new VideoFactory();
//        Video video = videoFactory.getVideo("java");
//        if(video == null){
//            return;
//        }
//        video.produce();

        VideoFactory videoFactory = new VideoFactory();
        Video video = videoFactory.getVideo(JavaVideo.class);
        if(video == null){
            return;
        }
        video.produce();
    }

}

四、工厂方法

4.1 定义

定义:
创建一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行

适用场景:
1 创建对象需要大量重复的代码
2 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
3 一个类通过其子类来指定创建哪个对象

优点:
1 用户只需要关心产品对应的工厂,无需关系创建的细节
2 加入新产品符合开闭原则,提高扩展性

缺点:
1 类的个数容易过多,增加复杂度
2 增加了系统抽象性和理解难度

4.2 类图

VideoFactory是抽象类
FEV、Python、Java实现抽象类VideoFactory,规定了方法
Video是一个抽象类
FEV、Python、Java实现抽象类Video,规定了方法
image.png
image.png

4.3 产品的代码

package com.geely.design.pattern.creational.factorymethod;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public abstract class Video {
    public abstract void produce();

}

package com.geely.design.pattern.creational.factorymethod;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class PythonVideo extends Video {
    @Override
    public void produce() {
        System.out.println("录制Python课程视频");
    }
}

package com.geely.design.pattern.creational.factorymethod;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class JavaVideo extends Video {
    @Override
    public void produce() {
        System.out.println("录制Java课程视频");
    }
}

package com.geely.design.pattern.creational.factorymethod;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class FEVideo extends Video{
    @Override
    public void produce() {
        System.out.println("录制FE课程视频");
    }
}

4.4 工厂的代码

package com.geely.design.pattern.creational.factorymethod;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public abstract class VideoFactory {
    public abstract Video getVideo();
}

package com.geely.design.pattern.creational.factorymethod;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class FEVideoFactory extends VideoFactory{
    @Override
    public Video getVideo() {
        return new FEVideo();
    }
}

package com.geely.design.pattern.creational.factorymethod;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class JavaVideoFactory extends VideoFactory {
    @Override
    public Video getVideo() {
        return new JavaVideo();
    }
}

package com.geely.design.pattern.creational.factorymethod;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class PythonVideoFactory extends VideoFactory {
    @Override
    public Video getVideo() {
        return new PythonVideo();
    }
}

4.5 测试类

package com.geely.design.pattern.creational.factorymethod;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class Test {
    public static void main(String[] args) {
        VideoFactory videoFactory = new PythonVideoFactory();
        VideoFactory videoFactory2 = new JavaVideoFactory();
        VideoFactory videoFactory3 = new FEVideoFactory();
        Video video = videoFactory.getVideo();
        video.produce();

    }

}

五、抽象工厂

5.1 定义

定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,无需指定他们具体的类

适用场景:
1 客户端不依赖产品类实例如何被创建、实现等细节
2 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码
3 提供一个产品类的库,所有产品以同样的接口出现,从而使客户端不依赖于具体实现

优点:
1 具体产品再应用层代码隔离,无需关心创建细节
2 将一系列的产品族统一到一起创建

缺点:
1 规定了所有可能被创建的产品集合,产品族种扩展新的产品困难,需要修改抽象工厂接口
2 增加了系统抽象性和理解程度

产品族和产品等级结构示意图

工厂方法:针对产品等级结构
抽象工厂:针对产品族

image.png
image.png

5.2 类图

假设现在慕课网工厂生产对象,课程对象和笔记对象,这时如果用工厂方法就会类爆炸,采用抽象工厂会好一点

image.png

image.png

5.3 Artical代码

package com.geely.design.pattern.creational.abstractfactory;

public abstract class Article {
    public abstract void produce();
}

package com.geely.design.pattern.creational.abstractfactory;


public class JavaArticle extends Article {
    @Override
    public void produce() {
        System.out.println("编写Java课程手记");
    }
}

package com.geely.design.pattern.creational.abstractfactory;


public class PythonArticle extends Article {
    @Override
    public void produce() {
        System.out.println("编写Python课程手记");
    }
}

5.4 Video代码

package com.geely.design.pattern.creational.abstractfactory;


public abstract class Video {
    public abstract void produce();

}

package com.geely.design.pattern.creational.abstractfactory;


public class PythonVideo extends Video {
    @Override
    public void produce() {
        System.out.println("录制Python课程视频");
    }
}

package com.geely.design.pattern.creational.abstractfactory;


public class JavaVideo extends Video {
    @Override
    public void produce() {
        System.out.println("录制Java课程视频");
    }
}

5.5 Factory代码

package com.geely.design.pattern.creational.abstractfactory;


public interface CourseFactory {
    Video getVideo();
    Article getArticle();

}

package com.geely.design.pattern.creational.abstractfactory;


public class JavaCourseFactory implements CourseFactory {
    @Override
    public Video getVideo() {
        return new JavaVideo();
    }

    @Override
    public Article getArticle() {
        return new JavaArticle();
    }
}

package com.geely.design.pattern.creational.abstractfactory;


public class PythonCourseFactory implements CourseFactory {
    @Override
    public Video getVideo() {
        return new PythonVideo();
    }

    @Override
    public Article getArticle() {
        return new PythonArticle();
    }
}

5.6 Test测试代码

如果再增加算法课程,就不用修改其他也可以扩展

package com.geely.design.pattern.creational.abstractfactory;

public class Test {
    public static void main(String[] args) {
        CourseFactory courseFactory = new JavaCourseFactory();
        Video video = courseFactory.getVideo();
        Article article = courseFactory.getArticle();
        video.produce();
        article.produce();
    }
}

六、建造者模式

6.1 定义

定义:
1 将一个复杂对象的构建与他的表示分离,使得同样得构建过程可以创建不用得表示
2 用户只需要指定需要建造得类型就可以得到他们,建造过程及细节不需要知道

适用场景:
1 如果一个对象有非常复杂得内部结构(很多属性)
2 想把复杂对象得创建和使用分离

优点:
1 封装性好,创建和使用分离
2 扩展性好、建造类之间独立、一定程度上解耦

缺点:
1 产生多余得Builder对象
2 产品内部发生变化,建造者都要修改,成本较大

建造者和工厂的不同

1 建造者更注重方法的调用顺序
2 工厂注重于创建产品
3 创建对象的粒度不同,工厂创建的都是一样的,建造者创建复杂产品,由各种部件组成

6.2 类图

业务场景:慕课网要发布课程,课程内容包括(ppt、名字、视频、课件、问答),还需要一个讲师负责完成这些内容,涉及到复杂对象的创建

image.png

6.3 Builder代码

package com.geely.design.pattern.creational.builder;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public abstract class CourseBuilder {

    public abstract void buildCourseName(String courseName);
    public abstract void buildCoursePPT(String coursePPT);
    public abstract void buildCourseVideo(String courseVideo);
    public abstract void buildCourseArticle(String courseArticle);
    public abstract void buildCourseQA(String courseQA);

    public abstract Course makeCourse();

}

package com.geely.design.pattern.creational.builder;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class CourseActualBuilder extends CourseBuilder {

    private Course course = new Course();


    @Override
    public void buildCourseName(String courseName) {
        course.setCourseName(courseName);
    }

    @Override
    public void buildCoursePPT(String coursePPT) {
        course.setCoursePPT(coursePPT);
    }

    @Override
    public void buildCourseVideo(String courseVideo) {
        course.setCourseVideo(courseVideo);
    }

    @Override
    public void buildCourseArticle(String courseArticle) {
        course.setCourseArticle(courseArticle);
    }

    @Override
    public void buildCourseQA(String courseQA) {
        course.setCourseQA(courseQA);
    }

    @Override
    public Course makeCourse() {
        return course;
    }
}

6.4 Course代码

package com.geely.design.pattern.creational.builder;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class Course {
    private String courseName;
    private String coursePPT;
    private String courseVideo;
    private String courseArticle;

    //question & answer
    private String courseQA;

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public String getCoursePPT() {
        return coursePPT;
    }

    public void setCoursePPT(String coursePPT) {
        this.coursePPT = coursePPT;
    }

    public String getCourseVideo() {
        return courseVideo;
    }

    public void setCourseVideo(String courseVideo) {
        this.courseVideo = courseVideo;
    }

    public String getCourseArticle() {
        return courseArticle;
    }

    public void setCourseArticle(String courseArticle) {
        this.courseArticle = courseArticle;
    }

    public String getCourseQA() {
        return courseQA;
    }

    public void setCourseQA(String courseQA) {
        this.courseQA = courseQA;
    }

    @Override
    public String toString() {
        return "Course{" +
                "courseName='" + courseName + '\'' +
                ", coursePPT='" + coursePPT + '\'' +
                ", courseVideo='" + courseVideo + '\'' +
                ", courseArticle='" + courseArticle + '\'' +
                ", courseQA='" + courseQA + '\'' +
                '}';
    }
}

6.5 Coach代码

package com.geely.design.pattern.creational.builder;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class Coach {
    private CourseBuilder courseBuilder;

    public void setCourseBuilder(CourseBuilder courseBuilder) {
        this.courseBuilder = courseBuilder;
    }

    public Course makeCourse(String courseName,String coursePPT,
                             String courseVideo,String courseArticle,
                             String courseQA){
        this.courseBuilder.buildCourseName(courseName);
        this.courseBuilder.buildCoursePPT(coursePPT);
        this.courseBuilder.buildCourseVideo(courseVideo);
        this.courseBuilder.buildCourseArticle(courseArticle);
        this.courseBuilder.buildCourseQA(courseQA);
        return this.courseBuilder.makeCourse();
    }
}

6.6 Test

package com.geely.design.pattern.creational.builder;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class Test {
    public static void main(String[] args) {
        CourseBuilder courseBuilder = new CourseActualBuilder();
        Coach coach = new Coach();
        coach.setCourseBuilder(courseBuilder);

        Course course = coach.makeCourse("Java设计模式精讲",
                "Java设计模式精讲PPT",
                "Java设计模式精讲视频",
                "Java设计模式精讲手记",
                "Java设计模式精讲问答");
        System.out.println(course);

    }
}

6.7 v2版本

image.png

实体类和实体类的Builder写在一起,这种写法最常用

package com.geely.design.pattern.creational.builder.v2;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class Course {

    private String courseName;
    private String coursePPT;
    private String courseVideo;
    private String courseArticle;

    //question & answer
    private String courseQA;

    public Course(CourseBuilder courseBuilder) {
        this.courseName = courseBuilder.courseName;
        this.coursePPT = courseBuilder.coursePPT;
        this.courseVideo = courseBuilder.courseVideo;
        this.courseArticle = courseBuilder.courseArticle;
        this.courseQA = courseBuilder.courseQA;
    }


    @Override
    public String toString() {
        return "Course{" +
                "courseName='" + courseName + '\'' +
                ", coursePPT='" + coursePPT + '\'' +
                ", courseVideo='" + courseVideo + '\'' +
                ", courseArticle='" + courseArticle + '\'' +
                ", courseQA='" + courseQA + '\'' +
                '}';
    }

    public static class CourseBuilder{
        private String courseName;
        private String coursePPT;
        private String courseVideo;
        private String courseArticle;

        //question & answer
        private String courseQA;

        public CourseBuilder buildCourseName(String courseName){
            this.courseName = courseName;
            return this;
        }


        public CourseBuilder buildCoursePPT(String coursePPT) {
            this.coursePPT = coursePPT;
            return this;
        }

        public CourseBuilder buildCourseVideo(String courseVideo) {
            this.courseVideo = courseVideo;
            return this;
        }

        public CourseBuilder buildCourseArticle(String courseArticle) {
            this.courseArticle = courseArticle;
            return this;
        }

        public CourseBuilder buildCourseQA(String courseQA) {
            this.courseQA = courseQA;
            return this;
        }

        public Course build(){
            return new Course(this);
        }



    }
}

package com.geely.design.pattern.creational.builder.v2;

import com.google.common.collect.ImmutableSet;

import java.util.Set;

/**
 * @Author CandyDingDing
 * @Version 1.0
 * @Motto 且视他人之疑目如盏盏鬼火,大胆地去走吾之夜路
 * @Describe 
 * @Date 2022/4/9
 */
public class Test {
    public static void main(String[] args) {
        Course course = new Course.CourseBuilder().buildCourseName("Java设计模式精讲").buildCoursePPT("Java设计模式精讲PPT").buildCourseVideo("Java设计模式精讲视频").build();
        System.out.println(course);

        Set<String> set = ImmutableSet.<String>builder().add("a").add("b").build();

        System.out.println(set);
    }
}

参考

慕课网视频地址:https://coding.imooc.com/class/270.html
文档地址:https://www.yuque.com/lililil-9bxsv/kb/bnuf7w
代码地址:https://gitee.com/candydingding/design-pattern.git
视频网盘链接:https://pan.baidu.com/s/1AVqkDa1uAF6mNKH4tD5Vyg 提取码:12ol

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CandyDingDing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值