IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 软件设计模式的学习 -> 正文阅读

[PHP知识库]软件设计模式的学习


一、软件设计模式

软件设计模式(Software Design Pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。

也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。

软件设计模式的优点:

  1. 可以提高程序员的思维能力,编程能力和设计能力。

  2. 使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。

  3. 使设计的代码可重用性高,可读性强,可靠性好,灵活性好,可维护性强。


二、单例模式


1. 定义

指一个类只有一个实例,且该类能自行创建这个实例的一种模式。

例:

  1. 一个班级只有一个班主任。
  2. Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
  3. 一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

2. 特点

  • 单例类只能有一个实例。

  • 单例类必须自己创建自己的唯一实例。

  • 单例类必须给所有其他对象提供这一实例。


3. 实现方式

单例模式常见的实现方式有:懒汉模式饥汉模式双重校验锁静态内部类枚举,下面对五种方式进行具体的实现(以Java为例)。

3.1 懒汉模式

用的时候才去检查有没有实例,如果有则返回,没有则新建.

public class LazyTest {
    private static LazyTest instance = null;
    private LazyTest(){}

    public static synchronized LazyTest getInstance(){
        if(instance == null){
            instance = new LazyTest();
        }
        return instance;
    }
}

优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。


3.2 饿汉模式

饿汉模式相比懒汉模式,在类加载的时候就已经存在一个实例

public class HungryTest {
    private static HungryTest instance = new HungryTest();
    private HungryTest(){}

    public static HungryTest getInstance(){
        return instance;
    }

}

优点:没有加锁,执行效率会提高。没有线程安全的问题。
缺点:类加载时就初始化,可能产生很多无用的实例,浪费内存。


3.3 双重校验锁

综合了懒汉式和饿汉式两者的优缺点整合而成,采用双锁机制。

代码实现中,特点是在synchronized关键字内外都加了一层 if 条件判断,这样既保证了线程安全,又比直接上锁提高了执行效率,还节省了内存空间。但是,实现较复杂。

public class DLockTest {
    private static DLockTest instance = null;
    private DLockTest(){}

    public static DLockTest getInstance(){
        if(instance == null){
            synchronized (DLockTest.class){
                if (instance == null){
                    instance = new DLockTest();
                }
            }
        }
        
        return instance;
    }

}


3.4 静态内部类

public class StaticSingleTest {
    private static class SingleClass{
        private static StaticSingleTest instance = new StaticSingleTest();
    }

    private StaticSingleTest(){}
    public static StaticSingleTest getInstance(){
        return SingleClass.instance;
    }

}

静态内部类的方式效果类似双检锁,但实现更简单。

对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。

这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。


3.5 枚举

public enum EnumTest {
    INSTANCE;
    public void whateverMethod() {
    }
}

这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。

它更简洁,不仅能避免多线程同步问题,还自动支持序列化机制,绝对防止多次实例化。


4. 应用场景

对于 Java 来说,单例模式可以保证在一个 JVM 中只存在单一实例。

单例模式的应用场景主要有以下几个方面:

  • 需要频繁创建的一些类,使用单例可以降低系统的内存压力,减少 GC。

  • 某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。

  • 某些类创建实例时占用资源较多,或实例化耗时较长,且经常使用。

  • 某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。

  • 频繁访问数据库或文件的对象。

  • 对于一些控制硬件级别的操作,或者从系统上来讲应当是单一控制逻辑的操作,如果有多个实例,则系统会完全乱套。

  • 当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。



三、工厂模式

1. 定义

工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。

简单点来说,工厂模式就是提供一个产生实例化对象的制造厂,每一个工厂都会提供类似的对象(实现共同接口),当我们需要某个类的实例化对象时,我们不需要关心服务端是通过什么方式来获取对象的,我们直接向对应的工厂提出我们的需求即可(实现了客户端和服务端的分离)。


2. 分类

工厂模式有 3 种不同的实现方式,分别是简单工厂模式工厂方法模式抽象工厂模式

2.1 简单工厂模式

我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫**“简单工厂模式”**。

在简单工厂模式中创建实例的方法通常为静态(static)方法

因此简单工厂模式(Simple Factory Pattern)又叫作静态工厂方法模式(Static Factory Method Pattern)

public class Client {
    //抽象产品
    public interface Product {
        void show();
    }
    //具体产品:ProductA
    static class ConcreteProduct1 implements Product {
        public void show() {
            System.out.println("具体产品1显示...");
        }
    }
    //具体产品:ProductB
    static class ConcreteProduct2 implements Product {
        public void show() {
            System.out.println("具体产品2显示...");
        }
    }
    final class Const {
        static final int PRODUCT_A = 0;
        static final int PRODUCT_B = 1;
        static final int PRODUCT_C = 2;
    }
    static class SimpleFactory {
        public static Product makeProduct(int kind) {
            switch (kind) {
                case Const.PRODUCT_A:
                    return new ConcreteProduct1();
                case Const.PRODUCT_B:
                    return new ConcreteProduct2();
            }
            return null;
        }
    }
}

2.2 工厂方法模式

前面我们说了简单工厂模式违背了开闭原则,而**“工厂方法模式”**是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。

public class AbstractFactoryTest {
    public static void main(String[] args) {
        try {
            Product a;
            AbstractFactory af;
            af = (AbstractFactory) ReadXML.getObject();
            //抽象工厂内容放入到外部配置文件xml/properties等文件中,通过I/O流加载从而创建出抽象工厂
            a = af.newProduct();
            a.show();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}
//抽象产品:提供了产品的接口
interface Product {
    public void show();
}
//具体产品1:实现抽象产品中的抽象方法
class ConcreteProduct1 implements Product {
    public void show() {
        System.out.println("具体产品1显示...");
    }
}
//具体产品2:实现抽象产品中的抽象方法
class ConcreteProduct2 implements Product {
    public void show() {
        System.out.println("具体产品2显示...");
    }
}
//抽象工厂:提供了厂品的生成方法
interface AbstractFactory {
    public Product newProduct();
}
//具体工厂1:实现了厂品的生成方法
class ConcreteFactory1 implements AbstractFactory {
    public Product newProduct() {
        System.out.println("具体工厂1生成-->具体产品1...");
        return new ConcreteProduct1();
    }
}
//具体工厂2:实现了厂品的生成方法
class ConcreteFactory2 implements AbstractFactory {
    public Product newProduct() {
        System.out.println("具体工厂2生成-->具体产品2...");
        return new ConcreteProduct2();
    }
}
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
/**
 * @author hz
 * @version 1.0
 */
public class ReadXML {
    //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
    public static Object getObject() {
        try {
            //创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File("src/FactoryMethod/config1.xml"));
            //获取包含类名的文本节点
            NodeList nl = doc.getElementsByTagName("className");
            Node classNode = nl.item(0).getFirstChild();
            String cName = "FactoryMethod." + classNode.getNodeValue();
            //System.out.println("新类名:"+cName);
            //通过类名生成实例对象并将其返回
            Class<?> c = Class.forName(cName);
            Object obj = c.newInstance();
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

2.3 抽象工厂模式

抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构,这里便出现了两个概念:同族和同等级。

使用抽象工厂模式需要满足以下条件:

  • 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。

  • 系统一次只可能消费其中某一族产品,即同族的产品一起使用。

public class FarmTest {
    public static void main(String[] args) {
        try {
            Farm f;
            Animal a;
            Plant p;
            //读取相应的配置信息,用于生产工厂
            f = (Farm) ReadXML.getObject();
            a = f.newAnimal();
            p = f.newPlant();
            a.show();
            p.show();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}
//抽象产品:动物类
interface Animal {
    public void show();
}
//具体产品:马类
class Horse implements Animal {
    public Horse() {
        System.out.println("具体马类的生成");
    }
    public void show() {
        System.out.println("执行马类的相应操作");
    }
}
//具体产品:牛类
class Cattle implements Animal {

    public Cattle() {
        //具体牛类的生成
        System.out.println("具体牛类的生成");
    }
    public void show() {
        System.out.println("执行马类的相应操作");
    }
}
//抽象产品:植物类
interface Plant {
    public void show();
}
//具体产品:水果类
class Fruitage implements Plant {

    public Fruitage() {
        System.out.println("具体水果类生成");
    }
    public void show() {
        System.out.println("执行水果类的相应操作");
    }
}
//具体产品:蔬菜类
class Vegetables implements Plant {
    public Vegetables() {
        System.out.println("具体蔬菜类生成");
    }
    public void show() {
        System.out.println("执行蔬菜类的相应操作");
    }
}
//抽象工厂:农场类
interface Farm {
    public Animal newAnimal();
    public Plant newPlant();
}
//具体工厂:农场类1
class SGfarm implements Farm {
    public Animal newAnimal() {
        System.out.println("新牛出生!");
        return new Cattle();
    }
    public Plant newPlant() {
        System.out.println("蔬菜长成!");
        return new Vegetables();
    }
}
//具体工厂:农场类2
class SRfarm implements Farm {
    public Animal newAnimal() {
        System.out.println("新马出生!");
        return new Horse();
    }
    public Plant newPlant() {
        System.out.println("水果长成!");
        return new Fruitage();
    }
}
import org.w3c.dom.*;
import javax.xml.parsers.*;
import java.io.File;

/**
 * @author hz
 * @version 1.0
 */
public class ReadXML2 {
    public static Object getObject() {
        try {
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File("src/AbstractFactory/config.xml"));
            NodeList nl = doc.getElementsByTagName("className");
            Node classNode = nl.item(0).getFirstChild();
            String cName = "AbstractFactory." + classNode.getNodeValue();
            System.out.println("新类名:" + cName);
            Class<?> c = Class.forName(cName);
            Object obj = c.newInstance();
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

抽象工厂模式的扩展有一定的“开闭原则”倾斜性.



四、总结

设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。正确使用设计模式具有以下优点。

可以提高程序员的思维能力、编程能力和设计能力。

使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。

使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。


参考

设计模式-单例模式
设计模式的学习
软件设计模式之单例模式
设计模式系列——抽象工厂模式

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 07:45:54  更:2021-09-19 07:46:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:15:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码