您现在的位置是:首页 >学无止境 >【设计模式二十三剑】✨编写更高质量代码的秘诀✨网站首页学无止境

【设计模式二十三剑】✨编写更高质量代码的秘诀✨

Fetters04 2024-06-17 10:29:51
简介【设计模式二十三剑】✨编写更高质量代码的秘诀✨

✨✨简述

?设计模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样就能一次又一次地使用该方案而不必做重复劳动。核心在于提供了相关问题的解决方案,使得人们可以更加简单方便地复用成功的设计和体系结构
?设计模式是在软件工程中广泛使用的经过反复验证的解决方案,它们可以用来解决常见的设计问题。设计模式是对软件开发中经常出现的一些问题的一种通用解决方案,它们可以提高软件的可维护性、可重用性、灵活性和可扩展性。设计模式提供了一种通用的词汇和标准术语,使软件开发人员可以更加清晰地交流和理解软件设计和实现。同时,设计模式还可以加快软件开发过程,提高开发效率。

?设计模式的四个基本要素模式名称、问题、解决方案、效果

??按照目的可以分为三类:

  • 创建型模式(Creational Patterns):主要关注对象的创建过程,包括如何实例化对象、如何组织对象的创建结构等。
  • 结构型模式(Structural Patterns):主要关注对象和类的组合方式,以及对象和类之间的组合方式。
  • 行为型模式(Behavioral Patterns):主要关注对象和类之间的通信方式,以及负责协调和控制类之间的交互。

模式分类

==========================================================================================

?【万能之门】简单工厂模式(Simple Factory)

?简单工厂模式属于创建型模式,但不属于23种设计模式之一。
简单工厂模式可以通过一个工厂类创建不同的对象,就像开启了一个万能的
门,可以制造出不同的产品。定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类 。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method) 模式,它属于类创建型模式

结构图如下:
在这里插入图片描述


??有三类角色

  • Factory(工厂角色):简单工厂模式的核心,负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象。
  • Product(抽象产品角色):工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象。
  • ConcreteProduct(具体产品角色):简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实力,它要实现抽象产品中声明的抽象方法。

代码实现:

public class SimpleFactory {
    public static void main(String[] args) {
        Product productA = Factory.createProduct("A");
        productA.info();
        
        Product productB = Factory.createProduct("B");
    }
}

// 抽象产品角色
abstract class Product {
    public abstract void info();
}

// 工厂角色
class Factory {
    public static Product createProduct(String type) {
        Product product = null;
        
        switch (type) {
            case "A":
                product = new ProductA();
                break;
            case "B":
                product = new ProductB();
                break;
            default:
                System.out.println("没有 " + type + " 类型的产品!");
                break;
        }
        
        return product;
    }
}

// 产品A
class ProductA extends Product {
    
    @Override
    public void info() {
        System.out.println("产品的信息:A");
    }
}

// 产品B
class ProductB extends Product {

    @Override
    public void info() {
        System.out.println("产品的信息:B");
    }
}

?优缺点:
【优点】
? 1、简单工厂模式将对象的创建过程集中在一个工厂类中,客户端无需知道具体的创建过程,只需要传递对应的参数即可创建对象,降低了客户端的复杂度和耦合度。
? 2、简单工厂模式可以根据不同的参数创建不同的对象,提高了代码的可扩展性和灵活性。
【缺点】
? 1、简单工厂模式的工厂类通常包含了所有的对象创建逻辑,如果需要增加新的产品,则需要修改工厂类的代码,违反了开闭原则。
? 2、工厂类负责创建所有的对象,当创建的对象过多时,工厂类会变得十分臃肿,难以维护。
? 3、简单工厂模式的扩展性有限,无法应对复杂的业务需求。

==========================================================================================

?【制造之剑】工厂方法模式(Factory Method)

【刀光剑影,转瞬即逝,千变万化,百般精通。】

? 工厂方法模式是一种创建型设计模式,是简单工厂模式的延伸,它提供了一种将对象的实例化过程封装在子类中进行的方法。在工厂方法模式中,抽象工厂定义了一个创建对象的接口,由其具体子类来决定要实例化的类,而具体实例化的过程则延迟到具体子类中进行

工厂方法模式将对象的创建过程分离出来,使得客户端不需要知道具体的实现细节,只需要知道一个工厂接口即可,从而使系统更加灵活可扩展。

在工厂方法模式中,通常会定义一个抽象工厂接口和若干个具体的工厂类,每个工厂类负责创建一种具体的产品对象。同时,定义一个抽象产品接口和若干个具体的产品类,每个产品类负责实现具体的产品功能。客户端通过工厂接口来创建产品对象,不同的工厂实现类对应不同的产品对象。

结构图如下:
在这里插入图片描述


? 工厂方法模式适用于:

  • 当一个类不知道它所必须创建的对象的类的时候。
  • 当一个类希望由它的子类来指定它所创建的对象的时候。
  • 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

代码实现:

public class FactoryMethod {
    public static void main(String[] args) {
        Factory factoryA = new FactoryA();
        // 父类 对象名 = new 子类();

        Product productA = factoryA.createProduct();
        // Product productA = new ProductA();
        productA.info();

        Factory factoryB = new FactoryB();

        Product productB = factoryB.createProduct();
        productB.info();
    }
}

// class Factory
interface Factory {
    public Product createProduct();
}

class FactoryA implements Factory {

    @Override
    public Product createProduct() {
        return new ProductA();
    }
}

class FactoryB implements Factory {

    @Override
    public Product createProduct() {
        return new ProductB();
    }
}

// abstract class Product
interface Product {
    // public abstract void info();
    public void info();
}

// class ProductA extends Product
class ProductA implements Product {

    @Override
    public void info() {
        System.out.println("产品的信息:A");
    }
}

// class ProductB extends Product
class ProductB implements Product {

    @Override
    public void info() {
        System.out.println("产品的信息:B");
    }
}

?优缺点:
【优点】
? 1、可以使系统更加灵活可扩展,可以动态地增加或修改产品类而不会影响到客户端代码。
? 2、符合“开闭原则”,即对扩展开放、对修改关闭,增加新的产品类只需要增加对应的工厂类即可,不需要修改原有代码。
? 3、降低了客户端和产品对象之间的耦合度,客户端只需要知道抽象工厂和抽象产品接口即可,具体的产品对象由具体的工厂类来创建。
? 4、工厂方法模式可以使用多态性,即客户端可以针对抽象工厂和抽象产品接口编程,而在运行时可以动态地替换具体的工厂类和产品类。
【缺点】
? 1、需要定义大量的类,增加了系统的复杂度。
? 2、工厂方法模式中的抽象产品类只能定义一些抽象的方法,而不能实现具体的功能,这限制了产品的功能扩展性。
? 3、客户端需要知道具体工厂类的存在,这增加了客户端的使用难度。

==========================================================================================

?【生产之剑】抽象工厂模式(Abstract Factory)

【刀刃之上,锋芒毕露,不止于形,更注重意。】

? 抽象工厂模式是一种创建型设计模式,它提供了一种接口,可以创建一系列相关或相互依赖的对象,而无需指定它们的具体类。它是工厂方法模式的一种升级版,工厂方法模式只能创建一种类型的对象,而抽象工厂模式可以创建多个不同类型的对象。它可以帮助客户端隔离具体类的创建,同时提供了一种将系统的各个部分组合起来的方法。

抽象工厂模式通常包含一个抽象工厂类和多个具体工厂类,每个具体工厂类负责创建一组相关的产品对象。抽象工厂类定义了用于创建这些产品对象的接口,而具体工厂类则实现了这些接口。

抽象工厂模式的核心是抽象工厂类,该类定义了一系列用于创建产品的方法,这些方法通常被设计为抽象的,这样具体的工厂类就必须实现这些方法来创建具体的产品对象。另外,抽象工厂类也可以定义一些公共的方法和属性,用于描述所创建的产品对象的特性

结构图如下:
在这里插入图片描述


?抽象工厂模式适用于:

  • 一个系统要独立于它的产品创建、组合和表示时。
  • 一个系统要由多个产品系列中的一个来配置时。
  • 当要强调一系列相关的产品对象的设计以便进行联合使用时。
  • 当提供一个产品类库,只想显示它们的接口而不是实现时。

代码实现:

public class AbstractFactory {
    public static void main(String[] args) {
        Factory factory1 = new Factory1();

        ProductA productA = factory1.createProductA();
        productA.info();

        Factory factory2 = new Factory2();

        ProductB productB = factory2.createProductB();
        productB.info();
    }
}

interface Factory {
    public ProductA createProductA();
    public ProductB createProductB();
}

class Factory1 implements Factory {

    @Override
    public ProductA createProductA() {
        return new ProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new ProductB1();
    }
}

class Factory2 implements Factory {

    @Override
    public ProductA createProductA() {
        return new ProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new ProductB2();
    }
}

interface ProductA {
    public void info();
}

class ProductA1 implements ProductA {

    @Override
    public void info() {
        System.out.println("产品的信息:A1");
    }
}

class ProductA2 implements ProductA {

    @Override
    public void info() {
        System.out.println("产品的信息:A2");
    }
}

interface ProductB {
    public void info();
}

class ProductB1 implements ProductB {

    @Override
    public void info() {
        System.out.println("产品的信息:B1");
    }
}

class ProductB2 implements ProductB {

    @Override
    public void info() {
        System.out.println("产品的信息:B2");
    }
}

?优缺点:
【优点】
? 1、可以保证同一工厂生产出的产品系列是相互关联或相互依赖的。
? 2、抽象工厂模式使得产品的切换变得容易,只需要更改具体工厂即可。
? 3、可以使客户端代码与具体产品的实现分离,客户端代码只需要关心抽象产品的接口,而不需要关心具体产品的实现。
【缺点】
? 1、抽象工厂模式的扩展性比较困难,因为抽象工厂接口中已经确定了可以创建的产品族,如果需要增加新的产品族,则需要修改抽象工厂接口,这样会影响到所有的具体工厂类。
? 2、增加新的产品等级结构(即增加新的抽象产品和相应的具体产品)比较困难,因为需要修改所有的具体工厂类。

==========================================================================================

?【组装之剑】构造者模式(Builder)

【慧眼识珠,从零开始,耐心细致,打造完美。】

? 构造者模式是一种创建型设计模式,用于创建复杂对象。它提供一种分步骤创建对象的方法,使得同样的构建过程可以创建不同的表示

构造者模式的核心概念是将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示形式。它通过一个构造者类(Builder)来封装对象的构建过程,并提供一系列的方法来设置对象的属性或组件。然后,通过调用构造者类的方法,逐步构建对象,最终返回构建好的对象。

结构图如下:

在这里插入图片描述


? 构造者模式适用于:

  • 当构造过程必须允许被构造的对象有不同表示时。
  • 当创建复杂对象的算法,应独立于该对象的组成部分、以及组装方式时。

代码实现:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Director director = new Director();

        Builder builder1 = new Builder1();
        director.Construct(builder1);
        Product product1 = builder1.getResult();
        product1.show();

        Builder builder2 = new Builder2();
        director.Construct(builder2);
        Product product2 = builder2.getResult();
        product2.show();
    }
}

class Director {
    public void Construct(Builder builder) {
        builder.BuildPart();
    }
}

abstract class Builder {
    public abstract void BuildPart();
    public abstract Product getResult();
}

class Builder1 extends Builder {
    Product product = new Product();

    @Override
    public void BuildPart() {
        product.Add("A");
        product.Add("B");
        product.Add("C");
        product.Add("D");
        product.Add("E");
        product.Add("F");
    }

    @Override
    public Product getResult() {
        return product;
    }
}

class Builder2 extends Builder {
    Product product = new Product();

    @Override
    public void BuildPart() {
        product.Add("A");
        product.Add("B");
        product.Add("C");
    }

    @Override
    public Product getResult() {
        return product;
    }
}

class Product {
    List<String> parts = new ArrayList<String>();

    public void Add(String part) {
        parts.add(part);
    }

    public void show() {
        System.out.print("产品的组成:");
        for (String s : parts)
            System.out.print(s + " ");

        System.out.print("
");
    }
}

?优缺点:
【优点】
? 1、封装复杂对象的构建过程:构造者模式将复杂对象的构建过程封装在一个独立的构造者类中,使得使用者无需关注对象的创建细节,只需通过简单的调用构造者的方法来构建对象。
? 2、可以创建不同表示的对象:通过调整构造者的步骤和顺序,可以创建具有不同属性配置的对象,满足不同的需求。这种灵活性使得构造者模式在创建复杂对象时非常有用。
? 3、提高代码的可读性和可维护性:由于构造者模式将对象的构建过程拆分为多个步骤,并通过方法链式调用的方式进行配置,使得代码更加清晰、易读,也更易于维护和扩展。
? 4、逐步构建对象:构造者模式支持逐步构建对象,每一步都可以设置对象的属性或组件。这种逐步构建的方式使得构建过程更加灵活,可以根据需要动态调整对象的属性。
【缺点】
? 1、增加了代码量:构造者模式引入了额外的构造者类,增加了代码量和类的数量。对于简单的对象创建,使用构造者模式可能会显得过于繁琐。
? 2、增加了系统的开销:由于构造者模式要求逐步构建对象,可能会增加系统的开销。如果对象的创建过程简单且固定,使用构造者模式可能会显得冗余。
? 3、不适用于创建不可变对象:构造者模式通常用于创建可变对象,如果需要创建不可变对象,可能需要额外的处理来保证对象的不可变性。

==========================================================================================

?【复制之剑】原型模式(Prototype)

? 原型模式是一种创建型设计模式,它允许通过复制(克隆)现有对象来创建新对象,而无需显式地使用构造函数。该模式基于一个原型对象,通过复制该原型对象的属性和状态来创建新的对象实例,从而实现对象的复制和创建。

原型模式的核心思想是将对象的创建委托给原型对象,原型对象作为一个可复制的模板,定义了对象的结构和初始状态。通过克隆原型对象,可以创建出与原型相同的新对象,而且新对象的创建过程可以根据需要进行定制和扩展。

结构图如下:
在这里插入图片描述


? 原型模式适用于:

  • 一个系统要独立于它的产品的创建、构成和表示时。
  • 当要实例化的类是在运行时刻指定时,例如,通过动态装载。
  • 为了避免创建一个与产品类层次平行的工厂类层次时。
  • 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们,可能比每次用合适的状态手工实例化该类更方便一些。

代码实现:

public class Main {
    public static void main(String[] args) {
        Product product1 = new Product(2022, 5.28);
        System.out.println(product1.getId() + " " + product1.getPrice());

        // Product product2 = new Product(2022, 5.28);
        Product product2 = (Product) product1.Clone();
        System.out.println(product2.getId() + " " + product2.getPrice());

        Product product3 = (Product) product1.Clone();
        System.out.println(product3.getId() + " " + product3.getPrice());
    }
}

interface Prototype {
    public Object Clone();
}

class Product implements Prototype {
    private int id;
    private double price;

    public Product() {}

    public Product(int id, double price) {
        this.id = id;
        this.price = price;
    }

    public int getId() {
        return id;
    }

    public double getPrice() {
        return price;
    }

    @Override
    public Object Clone() {
        Product object = new Product();
        object.id = this.id;
        object.price = this.price;

        return object;
    }
}

?优缺点:
【优点】
? 1、简化对象创建:原型模式通过克隆原型对象来创建新对象,避免了使用复杂的构造函数进行对象初始化的过程,使对象创建变得简单和直观。
? 2、提高性能:与直接创建对象相比,克隆原型对象可以提高对象创建的速度,避免了重复的初始化过程,特别是对于创建开销较大的对象而言,性能的提升更为显著。
? 3、实现对象定制化:原型模式允许动态地添加或修改原型对象的属性和行为,通过修改原型对象的克隆结果,可以实现对象的个性化定制。
【缺点】
? 1、克隆对象的复杂性:某些对象的克隆可能涉及到引用类型属性的处理,需要特别注意对象的引用关系和克隆的深浅复制问题。复杂对象的克隆可能会增加代码的复杂性。
? 2、内存消耗:原型模式需要在内存中保存原型对象,当需要大量创建对象时,会增加内存消耗。特别是深克隆的情况下,可能会占用更多的内存空间。
? 3、克隆与继承的冲突:在某些语言中,原型模式与继承机制存在冲突,因为克隆对象是通过复制已有对象来创建的,而不是通过继承父类来创建。

==========================================================================================

?【孤独之剑】单例模式(Singleton)

? 单例模式是一种创建型设计模式,它确保一个类只有一个实例对象,并提供全局访问点。

在单例模式中,类的构造函数被私有化,防止外部代码直接实例化对象。而通过定义一个静态方法或静态变量,让类自身负责创建并管理唯一的实例对象。每次调用该静态方法时,都返回同一个实例对象。

结构图如下:
在这里插入图片描述


?单例模式适用于:

  • 当类只能有一个实例而且客户可以从一个 从所周知的访问点访问它时。
  • 当这个唯一实例应该是通过子类化可扩展的,并且客户无须更改代码就能使用一个扩展的实例时。

代码实现:

public class SingletonPattern {
    public static void main(String[] args) {
        // Singleton singleton1 = new Singleton();

        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        Singleton singleton3 = Singleton.getInstance();

        System.out.println(singleton1.getNumber() + " " + singleton2.getNumber() + " " + singleton3.getNumber());

        singleton1.setNumber(528);
        System.out.println(singleton1.getNumber() + " " + singleton2.getNumber() + " " + singleton3.getNumber());

    }
}

class Singleton {
    private int number = 2022;

    public void setNumber(int number) {
        this.number = number;
    }

    public int getNumber() {
        return number;
    }

    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}

?优缺点:
【优点】
? 1、确保只有一个实例:单例模式保证类只有一个实例对象,避免了多次实例化的开销和资源浪费。
? 2、全局访问点:通过单例模式,可以在程序的任何位置访问该实例对象,方便地共享和调用。
? 3、避免竞态条件:在多线程环境下,单例模式可以防止多个线程同时创建实例对象,避免了竞态条件和数据不一致的问题。
【缺点】
? 1、难以扩展和测试:因为单例模式将实例对象的创建和管理集中在类内部,对于扩展和测试来说可能会变得更加困难。
? 2、违反单一职责原则:单例模式负责创建和管理实例对象,可能导致类的职责不够清晰,违反了单一职责原则。

==========================================================================================

?【调和之剑】适配器模式(Adapter)

? 适配器模式是一种结构型设计模式,用于将一个类的接口转换成另一个接口,使得不兼容的类能够一起工作

适配器模式的核心概念是适配器(Adapter),它充当两个不兼容类之间的桥梁。适配器接受一个类的请求,并将其转换为另一个类可以理解的格式。

结构图如下:
在这里插入图片描述


?适配器模式适用于:

  • 想使用一个已经存在的类,而它的接口不符合要求。

将Type-C接口通过适配器插入到USB接口

在这里插入图片描述

代码实现:

public class AdapterPattern {
    public static void main(String[] args) {
        USB usb = new Adapter();
        usb.Request();
    }
}

class USB {
    public void Request() {
        System.out.println("USB数据线");
    }
}

class Adapter extends USB {
    private TypeC typeC = new TypeC();

    @Override
    public void Request() {
        typeC.SpecificRequest();
    }
}

class TypeC {
    public void SpecificRequest() {
        System.out.println("Type-C数据线");
    }
}

?【联通之剑】桥接模式(Bridge)

?【合力之剑】组合模式(Composite)

?【加持之剑】装饰器模式(Decorator)

?【掌控之剑】外观模式(Facade)

?【共享之剑】享元模式(Flyweight)

?【护卫之剑】代理模式(Proxy)

? 【承载之剑】责任链模式(Chain of Responsibility)

? 【掌舵之剑】命令模式(Command)

? 【解谜之剑】解释器模式(Interpreter)

? 【漫游之剑】迭代器模式(Iterator)

? 【调解之剑】中介者模式(Mediator)

? 【回溯之剑】备忘录模式(Memento)

? 【注视之剑】观察者模式(Observer)

? 【转换之剑】状态模式(State)

? 【取舍之剑】策略模式(Strategy)

? 【规范之剑】模板方法模式(Template Method)

? 【访问之剑】访问者模式(Visitor)

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。