首页 / 时尚 / 时装 / 正文

程序设计模式(2.5 万字详解:23 种设计模式)

放大字体  缩小字体 来源:致命紫罗兰2 2026-04-15 13:35  浏览次数:11
本文简述了各大设计模式,并通过UML和代码详细说明。本文大约共 2.5W 字,建议收藏。下方是本文的目录:

一、设计模式的认识

二、设计模式的分类

  • 根据其目的
  • 根据范围

三、设计模式的优点

四、设计模式中关键点

五、创建型模式

  • 简单(静态)工厂模式
  • 工厂方法模式
  • 抽象工厂模式
  • 单例模式
  • 原型模式
  • 建造者模式

六、个人体会

一、设计模式的认识

设计模式(Design Pattern)是前辈们经过相当长的一段时间的试验和错误总结出来的,是软件开发过程中面临的通用问题的解决方案。这些解决方案使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

二、设计模式的分类

(1)根据其目的

即模式是用来做什么的,可分为创建型(Creational),结构型(Structural)和行为型(Behavioral)三种:①创建型模式主要用于创建对象。②结构型模式主要用于处理类或对象的组合。③行为型模式主要用于描述对类或对象怎样交互和怎样分配职责。

(2) 根据范围

即模式主要是用于处理类之间关系还是处理对象之间的关系,可分为类模式和对象模式两种:类模式处理类和子类之间的关系,这些关系通过继承建立,在编译时刻就被确定下来,是属于静态的。对象模式处理对象间的关系,这些关系在运行时刻变化,更具动态性。

2.5 万字详解:23 种设计模式nerror="javascript:errorimg.call(this);"/>

UML说明:苹果手机和红米手机继承了手机这个抽象类,工厂类里根据客户端传入的参数生成相应的对象,如,客户说要红米,工厂给客户一个红米手机,客户说要苹果,工厂给客户一个苹果手机。

简单工厂有三个对象:①抽象产品类:提供抽象方法供具体产品类实现 ②具体产品类:提供具体的产品 ③工厂:根据内部逻辑返回相应的产品

3.代码实现

(1)抽象产品类Phone 这里可以是类,也可以是接口或者抽象类,千万不要思维定式。我比较喜欢面向接口编程,所以我这里用了接口。

public interface Phone {
void produce();
}

(2)具体产品类

在这里插入代码片public class ApplePhoneImpl implements Phone{
@Override
public void produce() {
System.out.println("生产苹果手机");
}
}
public class RedmiPhoneImpl implements Phone{
@Override
public void produce() {
System.out.println("生产了红米手机");
}
}

(3)工厂类

public class Factory {

public Phone getPhone(String type){
Phone phone = ;
if("红米".equals(type)){
phone = new RedmiPhoneImpl();
}else if("苹果".equals(type)){
phone = new ApplePhoneImpl();
}//.....
return phone;
}
}

(4)客户端使用

@Test
public void test1()
{
Factory factory = new Factory();

Phone redmiPhone = factory.getPhone("红米");
System.out.println(redmiPhone);
redmiPhone.produce();

Phone applePhone = factory.getPhone("苹果");
System.out.println(applePhone);
applePhone.produce();
}

运行结果如下:

2.5 万字详解:23 种设计模式nerror="javascript:errorimg.call(this);"/>

(3)总结优点:工厂类中的方法逻辑,是利用反射机制生成对象返回,好处是增加一种产品时,不需要修改工厂类中的代码。满足了开闭原则。
缺点:这种写法粗看牛逼,细想之下,不谈reflection的效率还有以下问题:个人觉得不好,因为Class.forName(clz.getName()).newInstance()调用的是无参构造函数生成对象,它和new Object()是一样的性质,而工厂方法应该用于复杂对象的初始化 ,当需要调用有参的构造函数时便无能为力了,这样像为了工厂而工厂,没有实际意义。2 不同的产品需要不同额外参数的时候 不支持。

6.再升级(重要)

(1)工厂类:

public class FactoryPlusPlus {


private static String className="com.wander.design.simplefactory.product.ApplePhoneImpl";

public static Phone getPhone() throws Exception {
return (Phone) Class.forName(className).newInstance();
}
}

2.5 万字详解:23 种设计模式nerror="javascript:errorimg.call(this);"/>

UML说明:苹果手机和红米手机实现了手机这个抽象类,苹果工厂和红米工厂实现了抽象工厂,苹果工厂当然要生产(依赖)苹果手机,红米工厂当然要生产(依赖)红米。客户要买苹果手机要去问苹果工厂要苹果手机,客户要买红米手机当然要去问红米工厂要红米手机。

工厂方法有四个对象:抽象产品类:提供抽象方法供具体产品类实现 具体产品类:提供具体的产品 抽象工厂:提供抽象方法供具体工厂实现 具体工厂:提供具体的工厂

3.代码实现

(1)抽象产品类和简单工厂的抽象产品类一样

(2)具体产品类和简单工厂的具体产品类一样

(3)抽象工厂

public interface Factory {
Phone getPhone();
}

(4)具体工厂

public class AppleFactoryImpl implements Factory{

@Override
public Phone getPhone() {
return new ApplePhoneImpl();
}
}

public class RedmiFactoryImpl implements Factory{
@Override
public Phone getPhone() {
return new RedmiPhoneImpl();
}
}

(5)客户端

@Test
public void test1()
{

Factory applePhoneFactory = new AppleFactoryImpl();
Factory redmiPhoneFactory = new RedmiFactoryImpl();

Phone applePhone = applePhoneFactory.getPhone();
Phone redmiPhone = redmiPhoneFactory.getPhone();

System.out.println(applePhone);
System.out.println(redmiPhone);

applePhone.produce();
redmiPhone.produce();
}

执行结果如下:

2.5 万字详解:23 种设计模式nerror="javascript:errorimg.call(this);"/>

UML说明:具体的苹果手机产品和具体的红米手机产品实现了手机产品抽象类,具体的苹果充电器产品和具体的红米充电器产品实现了充电器产品抽象类。具体的苹果工厂和具体的红米工厂实现了手机抽象工厂,然后苹果工厂生产苹果手机和苹果充电器,红米工厂生成红米手机和红米充电器。客户想要苹果手机和苹果充电器就要向苹果工厂要产品(对象),客户想要红米手机和红米充电器就要向红米工厂要产品(对象)。

工厂方法有四个对象:

抽象产品类:为每种具体产品声明接口,如图中Phone手机抽象类和Charger充电器抽象类

具体产品类:定义了工厂生产的具体产品对象,实现抽象产品接口声明的业务方法,如图中ApplePhoneImpl、RedmiPhoneImpl,AppleChargerImpl,RedmiChargerImpl

抽象工厂:它声明了一组用于创建一种产品的方法,每一个方法对应一种产品,如上述类图中的Factory就定义了两个方法,分别创建Phone和Charger

具体工厂:它实现了在抽象工厂中定义的创建产品的方法,生产一组具体产品,这组产品构件成了一个产品种类,每一个产品都位于某个产品等级结构中,如上述类图中的AppleFactoryImpl和RedmiFactoryImpl

3.代码实现

(1)抽象的产品

public interface Phone {
void produce();
}

public interface Charger {
void produce();
}

(2)具体的产品

① 苹果具体的产品

public class AppleChargerImpl implements Charger{

@Override
public void produce() {
System.out.println("生产苹果充电器");
}
}

public class ApplePhoneImpl implements Phone {
@Override
public void produce() {
System.out.println("生产苹果手机");
}
}

② 红米具体的产品

public class RedmiChargerImpl implements Charger{
@Override
public void produce() {
System.out.println("生产红米充电器");
}
}


public class RedmiPhoneImpl implements Phone {
@Override
public void produce() {
System.out.println("生产了红米手机");
}
}

(3)抽象工厂

public interface Factory {
Phone getPhone();

Charger getCharger();
}

(4)具体的工厂

public class AppleFactoryImpl implements Factory {

@Override
public Phone getPhone() {
return new ApplePhoneImpl();
}

@Override
public Charger getCharger() {
return new AppleChargerImpl();
}
}

public class RedmiFactoryImpl implements Factory {

@Override
public Phone getPhone() {
return new RedmiPhoneImpl();
}

@Override
public Charger getCharger() {
return new RedmiChargerImpl();
}
}


(5)执行结果

2.5 万字详解:23 种设计模式nerror="javascript:errorimg.call(this);"/>

UML说明:1.构造方法私有化:可以使得该类不被实例化即不能被new 2.在类本身里创建自己的对象 3.提供一个公共的方法供其他对象访问

3.代码实现

(1)饿汉式

①第一种:

public class Singleton {


private static final Singleton singleton = new Singleton();


private Singleton(){}


public static Singleton getSingleton() {
return singleton;
}
}

②第二种

public class SingletonStatic {

private static final SingletonStatic singletonStatic;


static {
singletonStatic = new SingletonStatic();
}

private SingletonStatic() {}

public static SingletonStatic getSingletonStatic(){
return singletonStatic;
}
}
说明:①优点:一般使用static和final修饰变量(具体作用已经在代码里描述了),只在类加载时才会初始化,以后都不会,线程绝对安全,无锁,效率高。
②缺点:类加载的时候就初始化,不管用不用,都占用空间,会消耗一定的性能(当然很小很小,几乎可以忽略不计,所以这种模式在很多场合十分常用而且十分简单)

:这里有两个小知识点:

a.如果是final非static成员,必须在构造器、代码块、或者直接定义赋值

b.如果是final static 成员变量,必须直接赋值 或者在静态代码块中赋值

(2)懒汉式
public class Singleton {

private static Singleton singleton = ;

private Singleton(){}

public static Singleton getSingleton() {
if(singleton == ){
singleton = new Singleton();
}
return singleton;
}
}


说明:Spring ioc 单例 是懒汉式 枚举上的升级

(9)ThreadLocal单例

2.5 万字详解:23 种设计模式nerror="javascript:errorimg.call(this);"/>

UML说明:实体类实现Cloneable接口,重写clone方法

3.代码实现

(1)Prototype类:

public class Prototype implements Cloneable {

private Integer id;
private String name;
private Map<String, Double> map;

@Override
protected Prototype clone() throws CloneNotSupportedException
{
//浅拷贝方式
Prototype prototype = (Prototype) super.clone();
//深拷贝方式:对每一个复杂类型分别进行克隆
//测试浅拷贝的时候注释下面代码
prototype.map = (Map<String, Double>) ((HashMap)this.map).clone();
return prototype;
}

public Prototype(Integer id, String name, Map<String, Double> map) {
this.id = id;
this.name = name;
this.map = map;
}

}


(3)执行结果:浅拷贝:

2.5 万字详解:23 种设计模式nerror="javascript:errorimg.call(this);"/>

改变其中一个对象map的值,该对象的map内容发生了变化,另一个对象map的内容没有发生变化

4.总结

优点:①提高了性能,在需要短时间创建大量的对象和创建对象很耗时的情况下,原型模式比通过new对象大大提高了时间效率。

② 逃避构造函数的约束。

缺点:

1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

2、实现原型模式每个派生类都必须实现 Clone接口。

5.应用场景

1.通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。比如,向数据库表插入多条测试数据,可以用到。

2.在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与Java融为浑然一体,大家可以随手拿来使用。

(6)建造者模式

1.认识:

①一句话来说:封装一个复杂对象的构建过程,并可以按步骤构造。因为需要对对象一步步建造起来,所以称为建造者模式。

②将复杂产品的构建过程封装分解在不同的方法中,使得创建过程非常清晰,能够让我们更加精确的控制复杂产品对象的创建过程,同时它隔离了复杂产品对象的创建和使用,使得相同的创建过程能够创建不同的产品。但是若内部变化复杂,会有很多的建造类。

2.UML类图:


3.具体建造者

public class ConcreteBuilder extends Builder {

@Override
public void buildPart1() {
System.out.println("建造part1");
}

@Override
public void buildPart2() {
System.out.println("建造part2");
}

@Override
public void buildPart3() {
System.out.println("建造part3");
}
}


5.客户端

public class Client {

@Test
public void test() {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.build();
}

}

6.执行结果

2.5 万字详解:23 种设计模式nerror="javascript:errorimg.call(this);"/>

4.总结

优点:1、建造者独立,易扩展。将复杂产品的构建过程封装分解在不同的方法中,使得创建过程非常清晰,能够让我们更加精确的控制复杂产品对象的创建过程。

2、便于控制细节风险。它隔离了复杂产品对象的创建和使用,使得相同的创建过程能够创建不同的产品。

缺点:1、产品必须有共同点,范围有限制。

2、如内部变化复杂,会有很多的建造类,导致系统庞大。

应用场景1、需要生成的对象具有复杂的内部结构。2、需要生成的对象内部属性本身相互依赖。

5.应用场景

JAVA 中的 StringBuilder。

六、个人体会

设计模式是一种解决问题的思维和方式,不要生搬硬套,为了设计模式而模式。本文作者:王德印,欢迎复制下方链接关注博主动态。

链接:https://blog.csdn.net/qq_41889508/article/details/105953114

2.5 万字详解:23 种设计模式nerror="javascript:errorimg.call(this);"/>


打赏
0相关评论
热门搜索排行
精彩图片
友情链接
声明:本站信息均由用户注册后自行发布,本站不承担任何法律责任。如有侵权请告知立立即做删除处理。
违法不良信息举报邮箱:115904045
头条快讯网 版权所有
中国互联网举报中心