很早以前,在我初学c语言的时候,我的第一个象样的程序是一个五子棋程序,使用了TC2.0的图形库,纯面向过程的设计,由上到下的设计,而且只有一个c文件就搞定了,大概几百行,可惜代码已经失传,非常可惜。
为什么要全局变量?
List 1
int
main()
{
int
s1,s2,s3;
fun1(s1);
fun2(s1,s2);
fun3(s1,s2,s3);
return
0;
}
上面的s1,s2,s3如果改成全局变量,则变为
List 2
int
s1,s2,s3;
int
main()
{
fun1();
fun2();
fun3();
}
似乎简洁了一些,而且没有了传递参数的开销。但是缺点也是很明显的,带了三个函数之间的耦合。
既然我们认识到全局变量的问题,怎么改进呢?
代码1中由于有三个变量,如果有更多的,就更麻烦,我们可以这样改进
List 3
typedef
struct
statusTag
{
int
s1,s2,s3;
}Status;
int
main()
{
Status s;
fun1(&s);
fun2(&s);
fun3(&s);
return
0;
}
这种技巧你可以在lua中看到,看lua的使用代码
List4
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
int
main(
int
argc,
char
*argv[])
{
lua_State *L = lua_open();
const
char
*buf = "var = 100";
int
var ;
luaopen_base(L);
luaopen_io(L);
lua_dostring(L, buf);
lua_getglobal(L, "var");
var = lua_tonumber(L, -1);
lua_close(L);
return
0;
}
请注意到这里的lua_open方法,这其实是一种创建自己的工厂方法。不使用全局变量的好处就是,我们保留了可以创建多个对象的自由。
时代在发展,进入C++时代,但是全局变量仍然有人在用,存在就是合理的。GOF提出一种设计模式叫Singleton的模式,其核心思想就是不让全局变量漂浮在空中,把它放入class中,成为衣冠楚楚的C++公民。著名的Meyer
Singleton像这样
List 5
class
Status
{
private
:
Status(){};
public
:
static
Status& getInstance()
{
static
Status s;
return
s;
}
};
class
User
{
void
fun()
{
Status &s = Status::Instance();
//. . .use s
}
};
一切似乎很完美,使用private来防止client 创建它,保证了对象的唯一性(注意:Meyer
singleton并不具有多线程安全,可能导致多次初始化对象)
但是随着 针对接口编程和单元测试越来越流行,singleton带来的对单元测试不友好的特点日益体现,全局变量不能很好的被mock,所以难于测试。
这时候所谓的IOC思想(Inversion
of Control,即反转模式)
出来了,简单的来说,就是通过构造函数或者set方法实现注入
List6 - 构造函数注入
class
Status{};
class
User
{
public
:
User(Status *s):m_ps(s){};
void
fun()
{
Status *s = m_ps;
}
private
:
Status *m_ps;
}
List7 - Set 注入
class
Status{};
class
User
{
public
:
User(){}
void
setStaus(Status *s)
{
m_ps = s;
}
void
fun()
{
Status *s = m_ps;
}
private
:
Status *m_ps;
}
使用IOC的好处是带来了更强大的灵活性,但是带来的问题就是调用者麻烦了(天下没有免费的午餐阿)
List8
int
main()
{
Status s;
User u;
u.setStatus(&s);
u.fun();
return
0;
}
好像一切又返朴归真,似乎并没有带来什么简单。有的时候简单和灵活性就是死对头。
为了简化用户进行手工注入,IOC容器出现,在Java世界里面,最著名的莫过于Spring了.IOC容器就像一个巨大的创建工厂,她可以使用xml来配置这些,这真的是一场革命。
<beans>
<bean id="status"
class
="Status">
</bean>
<bean id="user"
class
="User">
<property name="status"><
ref
bean="status"/></property>
</bean>
</beans>
Spring就是这样把注入的工作移到配置文件中去,提供了强大的灵活性和可配置性
但是由于c/c++ 不具备的java那么多运行期的类型识别和反射的功能,所以我目前还没有发现有在C++中使用的IOC容器,如果你知道,请告诉我
那么如果是C++怎么来使注入变得简单一点呢,可以使用工厂方法了
List9
User * createUser(Status &s,Status2 &s2)
{
User *user =
new
User();
user->setStatus(s);
user->setStatus2(s2);
return
user;
}
总结:
其实软件的设计根本就没有所谓的黄金法则,没有免
费的午餐,你在获得更强大的灵活性,往往都得到复杂性的附加效果。如果你就是写一个自己玩的小游戏,ok,你就是用全局变量。如果你要设计庞大的
Office,那你就没有办法把代码写的很简单,因为你要考虑的东西多了,可维护性,可测试性。
|
相关推荐
总的来说,IoC容器和Dependency Injection模式强调的是将对象的创建和管理职责从对象自身转移出去,从而提高代码的可复用性、可测试性和可维护性。在实际开发中,理解并应用这些模式有助于构建更健壮、灵活的软件...
Hibernate是一个对象关系映射(ORM)框架,它提供了从Java对象到数据库表的映射机制。在SSH架构中,Hibernate负责数据持久化层,实现对数据库的操作。 #### Hibernate配置 - **映射文件**:使用`.hbm.xml`文件或...
4. `Core`:核心文件夹可能包含MCU的核心功能代码,如初始化函数、系统时钟配置、全局变量和常量定义等。 5. `MDK-ARM`:这是Keil MDK-ARM的子文件夹,可能包含其他源文件、头文件和项目设置,用于构建整个工程。 ...
生鲜配送平台源码java Spring IoC控制反转 & DI依赖注入 Author:Qin Zhenghan 一、SpringIoC 高内聚、低耦合:首先...少使用全局变量。 类属性和方法的声明少用public,多用private关键字。 多用设计模式,比如采用
如果你想要声明让所有的 portlet 共用全局的存储变量的话,那么这全局变量需要存储在 global-session 中。application:与 servlet 应用相关全局作用域与 Servlet 中的 session 作用域效果相同。 8. Spring 管理...
2. VB、VB10和C#中的反模式:在VB和C#编程语言中,可能会遇到诸如过度使用全局变量、不恰当的事件处理、忽视异常处理、未充分利用面向对象特性等反模式。理解并避免这些反模式能提高代码的可读性、可维护性和性能。 ...
《Java 基础核心总结》 Java 概述 什么是 Java2 Java 的特点Java 开发环境 JDK JRE Java 开发环境配置 Java 基本语法 数据类型基础语法运算符 ...实例变量的特点全局变量 静态变量 静态变量的特点类变量 局部变量
这些类可能读取如`application.properties`这样的配置文件,设置全局变量,初始化数据库连接池、模板引擎等组件。 通过阅读和理解Spider-MVC的源码,开发者不仅可以了解到框架的运作原理,还可以学习到设计模式、...
2. 单例模式:确保一个类只有一个实例,并提供一个全局访问点,常用于控制共享资源的访问,如数据库连接。 3. 观察者模式:定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会...
"Inc"目录则可能包含相关的头文件,定义了函数原型和全局变量。"Drivers"目录可能包含STM32 HAL库或者其他驱动代码,用于配置和操作STM32的外设。 总的来说,这个示例项目旨在教会开发者如何利用STM32的EXTI和...
SenderReceiverInterface是一种提供者向特定内存写入数据,接收者读取该内存数据的方式,类似于全局变量。ClientServerInterface则是通过函数调用的形式,由Server提供服务以响应Client的请求。ModeSwitchInterface...
- **设计模式**:单例、工厂、装饰器、观察者、适配器等模式各有用途,例如单例用于保证全局只有一个实例,装饰器模式用于动态添加功能。 5. **依赖注入**: - **控制反转(IOC)**:对象的创建和管理权由外部...
### Spring从入门到精通知识点详解 #### 一、Spring框架简介 - **定义与起源**:Spring是一个开源的轻量级Java开发框架,由Rod Johnson创建,并于2003年发布首个版本。Spring框架的核心特性是依赖注入(Dependency ...
单例模式确保一个类只有一个实例,并提供全局访问点。常见的实现方式有饿汉式、懒汉式(线程安全和非线程安全)以及双重检查锁定(DCL)等。 3. **SQL统计**: 题目要求统计每个学生分数大于80分的课程数,可以...
其中,`.c`文件包含了应用的主函数和其他功能模块,`.h`文件则定义了函数原型和全局变量。工程文件用于构建、编译和调试程序。 为了在STM32F103C8T6上运行RT-Thread,我们需要进行以下步骤: 1. **配置RT-Thread**...
单例模式确保一个类只有一个实例,并提供一个全局访问点。在Java中实现单例模式最常见的方法包括懒汉式、饿汉式、双重检查锁定等。 **2. 工厂模式** 工厂模式提供了一个创建对象的接口,但允许子类决定实例化哪一...
- 避免全局变量,使用局部变量或类成员代替,减少副作用。 - 使用LINQ简化查询表达式,提高代码简洁度。 - 利用VB.NET的事件处理和委托,避免硬编码依赖。 4. **重构工具**: - Visual Studio IDE 自带的重构...
"Inc"中的头文件定义了相关函数的原型和全局变量,便于在不同源文件之间进行调用。 "Drivers"目录则包含了STM32CubeMX自动生成的HAL(Hardware Abstraction Layer,硬件抽象层)驱动库,这些库函数使得开发者可以更...
SSM框架的搭建涉及到Spring的依赖注入(IoC)和面向切面编程(AOP),SpringMVC的MVC设计模式,以及MyBatis的持久层操作。下面将详细介绍这三个框架的基本概念、开发环境搭建、Maven Web项目的创建以及SSM的整合步骤...
垃圾收集(GC)负责回收不再使用的对象所占的内存,而GC根节点是指能从全局变量、静态变量、线程栈等直接或间接引用的对象,如果一个对象没有任何GC根节点可达,那么它将被视为可回收的。 NIO(Non-blocking I/O)...