设计模式篇(DesignPattern - 前置知识 七大原则)(持续更新调整)

news2024/11/8 6:46:36

目录

前置知识

一、什么是设计模式

二、设计模式的目的

七大原则

原则一:单一职责原则

一、案例一:交通工具问题

1. 问题分析

2. 解决思路

2.1 类级别单一职责

2.2 方法级别单一职责

3. 知识小结

二、案例二:待更新

原则二:接口隔离原则

一、案例一:大接口拆分小接口

1. 问题分析

2. 解决思路

原则三:依赖倒转原则

一、案例一:面向接口编程

1. 问题分析

2. 依赖传递方式

2.1 通过接口实现依赖传递

2.2 通过构造方法实现依赖传递

2.3 通过setter实现依赖传递

3. 总结

原则四:里氏替换原则

一、案例一:基类问题

原则五:开闭原则

一、案例一:图形编辑问题

1. 问题分析

2. 解决思路

原则六:迪米特法则

一、案例一:直接朋友问题

 原则七:合成复用原则

一、案例一:继承聚合问题


前置知识

一、什么是设计模式

设计模式就是解决软件开发某些特定问题而提出的一些解决方案也可以理解成解决问题的思路。

二、设计模式的目的

设计模式的目的是为了提高代码重用性、可读性、可扩展性、可靠性,使得程序呈现出高内聚、低耦合的

特性。

  • 代码重用性:相同功能的代码无需多次重复编写
  • 可读性:编程按照一定规范,便于其他程序员的阅读和理解
  • 可扩展性:当我们可以非常方便简单地增加新功能
  • 可靠性:我们增加或删除部分功能时,对原有系统其他功能没有影响
  • 高内聚、低耦合:

高内聚就是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则

低耦合就是降低一个元素与其他元素之间的联系、感知和依赖

七大原则

设计模式原则,其实就是程序员编程时应当遵守的原则,也是各种设计模式的基础

(即为什么要这么设计的依据)。

  • 单一职责原则
  • 接口隔离原则
  • 依赖倒转原则
  • 里氏替换原则
  • 开闭原则
  • 迪米特法则
  • 合成复用原则

原则一:单一职责原则

一、案例一:交通工具问题

1. 问题分析

对于类来说,就是一个类应该只负责一项职责,如果类A负责了职责1和职责2,当职责1的需求发生改变时,可能对职责2的执行造成影

响,因此需要将类A分解为类A1和类A2。

例如下面举一个交通工具类的例子,当程序运行时会出现飞机在公路上运行的尴尬,就是因为这一个交通工具类既负责空中的,也负责陆

地的,才导致问题。

public class Main1 {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        vehicle.run("汽车");
        vehicle.run("飞机");
    }
}
//交通工具
class Vehicle{
    public void run(String vehicle){
        System.out.println(vehicle+"在公路上运行");
    }
}

2. 解决思路

2.1 类级别单一职责

将交通工具类分解为陆地交通工具和空中交通工具,使得一个类只负责一件事,如此虽然遵守了单一职责原则,但改动太大,为了一个方

法增加两个类,因此我们还能再简化。

public class Main1 {
    public static void main(String[] args) {
        RoadVehicle vehicle1 = new RoadVehicle();
        vehicle1.runRoad("汽车");
        AirVehicle vehicle2 = new AirVehicle();
        vehicle2.runAir("飞机");
    }
}
//交通工具
class RoadVehicle{
    public void runRoad(String vehicle){
        System.out.println(vehicle+"在陆地上运行");
    }
}
class AirVehicle{
    public void runAir(String vehicle){
        System.out.println(vehicle+"在天空上运行");
    }
}

2.2 方法级别单一职责

上面是在类级别上遵守单一职责,而下面这种是在方法级别上遵守单一职责。

class Vehicle{
    public void runAir(String vehicle){
        System.out.println(vehicle+"在天空上运行");
    }
    public void runRoad(String vehicle){
        System.out.println(vehicle+"在陆地上运行");
    }
}

3. 知识小结

  • 为了降低类的复杂度,做到一个类只负责一项职责;
  • 可以提高类的可读性和可维护性,降低变更引起的风险;
  • 通常情况下,我们应当逻辑单一职责原则,只有逻辑足够简单才能在代码上违反单一职责原则,只有类中方法数量很少,才可以只在方法级别上遵守单一职责原则。

二、案例二:待更新

原则二:接口隔离原则

一、案例一:大接口拆分小接口

1. 问题分析

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

为什么会有接口隔离?考虑这么一种情况,现有一个接口包含了三个方法,有类A和类B实现了该接口,而类C和

类D依赖于该接口。

(这里依赖的意思,类C和D中有方法的参数是接口,而我们可以将实现了接口的类A和B作为C和D方法的参

数)。下面用代码实现。

interface Interface1{
    void method1();
    void method2();
    void method3();
}
class A implements Interface1{

    @Override
    public void method1() {}
    @Override
    public void method2() {}
    @Override
    public void method3() {}
}
class B implements Interface1{

    @Override
    public void method1() {}

    @Override
    public void method2() {}

    @Override
    public void method3() {}
}
class C{
    public void c_method1(Interface1 interface1){
        interface1.method1();
    }
    public void c_method2(Interface1 interface1){
        interface1.method2();
    }
}
class D{
    public void d_method3(Interface1 interface1){
        interface1.method3();
    }
}

public class Main2 {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        C c = new C();
        c.c_method1(a);
        D d = new D();
        d.d_method3(b);
    }
}

2. 解决思路

这样的设计明显是有问题的,因为我们的类C只用到接口的方法一和方法二,而类D只用到了接口的方法三,因此

我们采用接口隔离,将接口分开。

把刚刚的接口Interface1拆分为接口Interface1和Interface2,使得类C和类D分别依赖两个不同接口。

interface Interface1{
    void method1();
    void method2();
}
interface Interface2{
    void method3();
}
class A implements Interface1{

    @Override
    public void method1() {}
    @Override
    public void method2() {}
}
class B implements Interface2{
    @Override
    public void method3() {}
}

class C{
    public void c_method1(Interface1 interface1){
        interface1.method1();
    }
    public void c_method2(Interface1 interface1){
        interface1.method2();
    }
}
class D{
    public void d_method3(Interface2 interface2){
        interface2.method3();
    }
}

原则三:依赖倒转原则

一、案例一:面向接口编程

1. 问题分析

  1. 高层模块不应该依赖底层模块,二者都应该依赖于抽象
  2. 抽象不应该依赖于细节,细节要依赖于抽象
  3. 抽象在Java中就是指接口或抽象类,细节就是具体的实现类
  4. 依赖倒转的中心思想就是面向接口编程
  5. 使用接口或抽象类的目的是为了制定好规范,而不涉及任何具体的作用,把展现细节的任务交给它们的实现类。

下面三种方式实现依赖传递:

2. 依赖传递方式

2.1 通过接口实现依赖传递

interface OpenInterface{
    public void open(TV tv);
}
interface TV{
    public void play();
}

class Open implements OpenInterface{

    @Override
    public void open(TV tv) {
        tv.play();
    }
}
class ChangHong implements TV{

    @Override
    public void play() {
        System.out.println("长虹电视打开了!");
    }
}


public class DependencyInversion {
    public static void main(String[] args) {
        ChangHong changHong = new ChangHong();
        OpenInterface openInterface = new Open();
        openInterface.open(changHong);
    }
}

2.2 通过构造方法实现依赖传递

interface OpenInterface{
    public void open();
}
interface TV{
    public void play();
}


class Open implements OpenInterface{
    public TV tv;
    Open(TV tv){
        this.tv = tv;
    }

    @Override
    public void open() {
        this.tv.play();
    }
}
class ChangHong implements TV{

    @Override
    public void play() {
        System.out.println("长虹电视打开了!");
    }
}

public class DependencyInversion {
    public static void main(String[] args) {
        ChangHong changHong = new ChangHong();
        OpenInterface openInterface = new Open(changHong);
    }
}

2.3 通过setter实现依赖传递

interface OpenInterface{
    public void open();
    public void setTV(TV tv);
}
interface TV{
    public void play();
}

class Open implements OpenInterface{
    public TV tv;

    @Override
    public void open() {
        this.tv.play();
    }

    @Override
    public void setTV(TV tv) {
        this.tv = tv;
    }
}
class ChangHong implements TV{

    @Override
    public void play() {
        System.out.println("长虹电视打开了!");
    }
}

public class DependencyInversion {
    public static void main(String[] args) {
        ChangHong changHong = new ChangHong();
        OpenInterface openInterface = new Open();
        openInterface.setTV(changHong);
        openInterface.open();
    }
}

3. 总结

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

原则四:里氏替换原则

一、案例一:基类问题

  • 所有引用基类的地方,必须能透明的使用其子类。
  • 因此,在继承时,子类尽量不要重写父类的方法。
  • 继承会让两个类的耦合性增强,因此适当情况下,可以通过聚合、组合、依赖来解决问题。(假如A继承于B,我们可以抽取其公共部分为Base类,然后使用组合,在A类中创建B的对象)
public class Liskov {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        A a = new A();
        System.out.println("11-3=" + a.func1(11, 3));
        System.out.println("1-8=" + a.func1(1, 8));
        System.out.println("-----------------------");
        B b = new B();
        //因为B类不再继承A类,因此调用者,不会再func1是求减法
        //调用完成的功能就会很明确
        System.out.println("11+3=" + b.func1(11, 3));//这里本意是求出11+3
        System.out.println("1+8=" + b.func1(1, 8));// 1+8
        System.out.println("11+3+9=" + b.func2(11, 3));
        //使用组合仍然可以使用到A类相关方法
        System.out.println("11-3=" + b.func3(11, 3));// 这里本意是求出11-3
    }

}

//创建一个更加基础的基类
class Base {
    //把更加基础的方法和成员写到Base类
}
// A类
class A extends Base {
    // 返回两个数的差
    public int func1(int num1, int num2) {
        return num1 - num2;
    }
}

// B类继承了A
// 增加了一个新功能:完成两个数相加,然后和9求和
class B extends Base {
    //如果B需要使用A类的方法,使用组合关系
    private A a = new A();
    //这里,重写了A类的方法, 可能是无意识
    public int func1(int a, int b) {
        return a + b;
    }
    public int func2(int a, int b) {
        return func1(a, b) + 9;
    }
    //我们仍然想使用A的方法
    public int func3(int a, int b) {
        return this.a.func1(a, b);
    }
}

原则五:开闭原则

一、案例一:图形编辑问题

1. 问题分析

  • 开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则
  • 一个软件实体,例如类、模块、函数应该对扩展开发(针对开发方),对修改关闭(针对使用方)。用抽象构建框架,用实现扩展细节。
  • 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有代码来实现变化。
  • 编程中遵循的其他原则,以及使用设计模式的目的就是遵守开闭原则。

下面举个例子:这种方式就没有遵循开闭原则,无论是扩展还是修改。假如要新增一个绘制三角形,就要改动很多。

public class Ocp {
    public static void main(String[] args) {
        GraphicEditor graphicEditor = new GraphicEditor();
        graphicEditor.drawRectangle(new Rectangle());
        graphicEditor.drawCircle(new Circle());
    }
}

//这是一个用于绘图的类【使用方】
class GraphicEditor{
    //根据不同类型来绘制不同图形
    public void drawShape(Shape shape){
        if (shape.type == 1)
            drawRectangle(shape);
        else if(shape.type == 2)
            drawCircle(shape);
    }

    public void drawRectangle(Shape r){
        System.out.println("矩形");
    }
    public void drawCircle(Shape c){
        System.out.println("圆形");
    }
}
//图形基类
class Shape{
    int type;
}
//矩形
class Rectangle extends Shape{
    Rectangle(){
        super.type = 1;
    }
}
//圆形
class Circle extends Shape{
    Circle(){
        super.type = 2;
    }
}

2. 解决思路

按照开闭原则方式优化:如果要绘制三角形,只需新增三角形类来继承Shape,既满足对扩展开发,也满足对修改关闭!

 

package design_principle.ocp.improve;

public class Ocp {
    public static void main(String[] args) {
        GraphicEditor graphicEditor = new GraphicEditor();
        graphicEditor.drawShape(new Rectangle());
        graphicEditor.drawShape(new Circle());
    }
}

//这是一个用于绘图的类【使用方】
class GraphicEditor{
    //根据不同类型来绘制不同图形
    public void drawShape(Shape shape){
        shape.draw();
    }
}

//图形基类
abstract class Shape{
    int type;
    public abstract void draw();
}

//矩形
class Rectangle extends Shape {
    Rectangle(){
        super.type = 1;
    }

    @Override
    public void draw() {
        System.out.println("矩形");
    }
}

//圆形
class Circle extends Shape {
    Circle(){
        super.type = 2;
    }

    @Override
    public void draw() {
        System.out.println("圆形");
    }
}

原则六:迪米特法则

一、案例一:直接朋友问题

  • 一个对象应该对其他对象保持最少的了解
  • 类与类关系越密切,耦合度越大
  • 迪米特法则也叫最少知道原则,即一个类对自己依赖的类知道的越少越好。对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供public方法外,不要泄露任何信息。
  • 迪米特法则还有个更简单的定义:只与直接朋友通信。
  • 直接朋友:只要两个对象间有耦合关系,那么它们就是朋友。耦合包括依赖、关联、组合、聚合等等。其中,我们将成员变量、方法参数、方法返回值中的类称为直接朋友,而出现在局部变量中的类(例如class A的一个方法里有class B对象)不是直接朋友。换句话说,陌生的类最好不要以局部变量的形式出现在类的内部。

注意:迪米特法则的核心只要求降低类之间的耦合,并不是完全没有依赖。

//客户端
public class Demeter {
    public static void main(String[] args) {
        System.out.println("~~~使用迪米特法则的改进~~~");
        //创建了一个 SchoolManager 对象
        SchoolManager schoolManager = new SchoolManager();
        //输出学院的员工id 和  学校总部的员工信息
        schoolManager.printAllEmployee(new CollegeManager());
    }
}


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

//学院的员工类
class CollegeEmployee {
    private String id;
    public void setId(String id) {
        this.id = id;
    }
    public String getId() {
        return id;
    }
}


//管理学院员工的管理类
class CollegeManager {
    //返回学院的所有员工
    public List<CollegeEmployee> getAllEmployee() {
        List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
        for (int i = 0; i < 10; i++) { //这里我们增加了10个员工到 list
            CollegeEmployee emp = new CollegeEmployee();
            emp.setId("学院员工id= " + i);
            list.add(emp);
        }
        return list;
    }
    //输出学院员工的信息
    public void printEmployee() {
        //获取到学院员工
        List<CollegeEmployee> list1 = getAllEmployee();
        System.out.println("------------学院员工------------");
        for (CollegeEmployee e : list1) {
            System.out.println(e.getId());
        }
    }
}

//学校管理类

//分析 SchoolManager 类的直接朋友类有哪些 Employee、CollegeManager
//CollegeEmployee 不是 直接朋友 而是一个陌生类,这样违背了 迪米特法则
class SchoolManager {
    //返回学校总部的员工
    public List<Employee> getAllEmployee() {
        List<Employee> list = new ArrayList<Employee>();
        for (int i = 0; i < 5; i++) { //这里我们增加了5个员工到 list
            Employee emp = new Employee();
            emp.setId("学校总部员工id= " + i);
            list.add(emp);
        }
        return list;
    }
    //该方法完成输出学校总部和学院员工信息(id)
    void printAllEmployee(CollegeManager sub) {
        //分析问题
        //1. 将输出学院的员工方法,封装到CollegeManager
        sub.printEmployee();
        //获取到学校总部员工
        List<Employee> list2 = this.getAllEmployee();
        System.out.println("------------学校总部员工------------");
        for (Employee e : list2) {
            System.out.println(e.getId());
        }
    }
}

 原则七:合成复用原则

一、案例一:继承聚合问题

尽量使用合成/聚合的方式,而不是使用继承。下面四种方式都可以让B使用A的方法,但继承的方式耦合度太高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2072903.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

本·阿弗莱克在与詹妮弗·洛佩兹离婚期间与孩子塞拉菲娜共度时光

在詹妮弗洛佩兹提出离婚申请期间&#xff0c;本阿弗莱克被发现与塞拉菲娜阿弗莱克一起在加州观看电影。 本阿弗莱克似乎将重心放在家庭时间上&#xff0c;最近有人拍到他带着孩子塞拉菲娜阿弗莱克在一起。此前&#xff0c;他的妻子詹妮弗洛佩兹 于 8 月 20 日星期二提出离婚。 …

小黄鸟九宫格切图丨教你如何将图片九宫格切图_照片分割成9张工具

图片九宫格怎么弄&#xff1f;怎么把1张图片切割称九宫图&#xff1f;如何将一张照片切成九宫格 微博九宫图怎么做&#xff1f;你还不知道电脑上如何做微博九宫格图片? 今天用小黄鸟九宫格切割工具&#xff0c;手把手教你,搞定九宫格切图 小黄九宫格切图丨小黄鸟教你如何九宫…

如何使用ssm实现基于web的药品管理系统+vue

TOC ssm175基于web的药品管理系统vue 第1章 绪论 1.1 课题背景 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。所以各行业&…

五、Centos7-安装Jenkins--这篇废了

克隆了一个base的虚拟机&#xff0c;用来安装Jenkins 2023年11月&#xff0c;Jenkins不支持centos7了。我们只是学习用&#xff0c;先看看吧。 &#xff08; 另一个人用别的操作系统安装的jenkins&#xff0c;可以参考 版权声明&#xff1a;本文为博主原创文章&#xff0c;…

js第五天-对象

object let obj {uname: pink,age: 18,gender: w} 增 对象名.属性新值 这个和cpp不一样&#xff0c;可以在大括号外面新增属性 <script>let obj {uname: pink,age: 18,gender: w}obj.hobby footballconsole.log(obj);</script>删 delete delete obj.gender …

Spring Boot整合MyBatis-Plus的详细讲解

MyBatis Plus&#xff08;简称MP&#xff09;是一个在MyBatis基础上进行增强的工具&#xff0c;它保留了MyBatis的所有特性&#xff0c;并通过提供额外的功能和简化操作来提高开发效率。以下是对MyBatis Plus的详细介绍&#xff1a; 一、基本概述 定义&#xff1a;MyBatis Plu…

【MATLAB学习笔记】绘图——设置次刻度线的数量、设置刻度线的宽度(粗细)和长度

目录 前言设置次刻度线数量函数示例基本绘图设置次刻度线数量函数的使用 设置刻度线的长度设置刻度线和轴线的宽度总代码总结 前言 在MATLAB中&#xff0c;将XMinorTicktrue或者YMinorTicktrue设置为true可以很方便地设置X轴或者Y轴次刻度线&#xff0c;但是次刻度线的数量是MA…

代码随想录DAY25 - 回溯算法 - 08/24

目录 非递减子序列 题干 思路和代码 递归法 递归优化 全排列 题干 思路和代码 递归法 全排列Ⅱ 题干 思路和代码 方法一&#xff1a;用集合 set 去重 方法二&#xff1a;先排序&#xff0c;再用数组去重 非递减子序列 题干 题目&#xff1a;给你一个整数数组 nu…

python动画:manim中的目标位置移动,线条末端和两条线相切的位置处理

一&#xff0c;Manim中目标的位置移动 在 Manim 中&#xff0c;shift 函数用于在三维空间或二维平面上对对象进行平移。通过 shift 方法&#xff0c;用户可以快速移动场景中的物体&#xff0c;指定移动的方向和距离。方向通常由预定义的常量&#xff08;如 UP, DOWN, LEFT, RI…

opencv-python图像增强十五:高级滤镜实现

文章目录 前言二、鲜食滤镜三、巧克力滤镜三&#xff0c;冷艳滤镜&#xff1a; 前言 在之前两个滤镜文章中介绍了六种简单的滤镜实现&#xff0c;它们大多都是由一个单独函数实现的接下来介绍五种结合了之前图像增强文章提的的算法的复合滤镜。本案例中的算法来自于文章一&…

【数学建模】TOPSIS法(优劣解距离法)

TOPSIS法&#xff08;Technique for Order Preference by Similarity to Ideal Solution&#xff0c;优劣解距离法&#xff09;是一种多准则决策分析方法&#xff0c;它基于这样一个概念&#xff1a;最理想的方案应该是距离理想解最近而距离负理想解最远的方案。以下是使用TOPS…

【React原理 - 任务调度和时间分片详解】

概述 在React15的时候&#xff0c;React使用的是从根节点往下递归的方式同步创建虚拟Dom&#xff0c;由于递归具有同步不可中断的特性&#xff0c;所以当执行长任务时(通常以60帧为标准&#xff0c;即16.6ms)就会长时间占用主线程长时间无响应&#xff0c;导致页面卡顿&#x…

如何使用Gitee管理自己的项目

如何使用Gitee管理自己的项目 前言 本地创建的工程项目不利于管理&#xff0c;电脑设备丢失损坏&#xff0c;代码就找不回来了。 并且多人同时使用一个项目工程也不方便。 国内的代码托管平台&#xff0c;Gitee为我实现了远程代码管理。 并且该平台可以设置为开源和私有两种…

公司邮箱如何建立

而建立一套完善的公司邮箱系统&#xff0c;则是实现这一目标的重要一环。本文将深入探讨公司邮箱的建立过程&#xff0c;以及其在业务中的重要性。 1. 确定邮箱域名 公司邮箱的建立首先要确定一个专属的邮箱域名。域名是公司在网络上的身份标识&#xff0c;例如&#xff0c;公…

程序猿成长之路之数据挖掘篇——Kmeans聚类算法

Kmeans 是一种可以将一个数据集按照距离&#xff08;相似度&#xff09;划分成不同类别的算法&#xff0c;它无需借助外部标记&#xff0c;因此也是一种无监督学习算法。 什么是聚类 用官方的话说聚类就是将物理或抽象对象的集合分成由类似的对象组成的多个类的过程。用自己的…

VSCode插件 live Server

普通打开 安装live Server 包含端口 说明内置了服务器

改造小蚁摄像头支持免费无限容量云储存(Samba挂载篇)

为什么要改造&#xff1f; 插卡摄像头最大的一个问题就是频繁的读写会导致内存卡寿命急速下降&#xff0c;哪怕是市面上支持NAS转存的摄像头也是先录制到SD卡里&#xff0c;然后把SD卡上的视频再转存到NAS。同样对内存卡和NAS硬盘寿命都是损耗巨大。而这类监控视频绝大多数情况…

重磅!小米将对外公开超 1000 万行的 Xiaomi Vela 开源代码

点击上方关注 “终端研发部” 设为“星标”&#xff0c;和你一起掌握更多数据库知识 如果说接下来的澎湃OS系统会带来很强的吸引力&#xff0c;那么第二个惊喜也是随之而来&#xff0c;那就是小米Vela开源大动作。 早在2017年起&#xff0c;小米就活跃于 NuttX 社区&#xff0c…

Reinforcement-Learning 2.State Value and Bellman Equation

目录 0.Outline 1.Motivating examples Motivating example 1: Why return is important? Motivating example 2: How to calculate return? 2.State value 3.Bellman equation: Derivation Deriving the Bellman equation An illustrative example Exercise 4.Be…

FreeSWITCH 1.10.10 简单图形化界面28 - 麒麟V10 SP3服务器系统X86和ARM版本安装FreeSWITCH

FreeSWITCH 1.10.10 简单图形化界面28 - 麒麟V10 SP3 服务器系统X86和ARM版本安装FreeSWITCH 界面预览00、先看使用手册01、 麒麟服务器v10 sp3 x86版本1、安装操作系统2、下载安装脚本3、安装 02、麒麟服务器v10 sp3 arm版本1、安装操作系统2、下载安装脚本3、安装 03、登录网…