当前位置:首页 > 代码 > 正文

代码设计实例(代码编程实例)[20240428更新]

admin 发布:2024-04-28 16:44 126


今天给各位分享代码设计实例的知识,其中也会对代码编程实例进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

《单片机C语言程序设计实训100例——基于8051+Proteus仿真》 第03篇源代码

单片机c语言编程100个实例目录1

函数的使用和熟悉

实例3:用单片机控制第一个灯亮

实例4:用单片机控制一个灯闪烁:认识单片机的工作频率

实例5:将 P1口状态分别送入P0、P2、P3口:认识I/O口的引脚功能

实例6:使用P3口流水点亮8位LED

实例7:通过对P3口地址的操作流水点亮8位LED

实例8:用不同数据类型控制灯闪烁时间

实例9:用P0口、P1 口分别显示加法和减法运算结果

实例10:用P0、P1口显示乘法运算结果

实例11:用P1、P0口显示除法运算结果

实例12:用自增运算控制P0口8位LED流水花样

实例13:用P0口显示逻辑"与"运算结果

实例14:用P0口显示条件运算结果

实例15:用P0口显示按位"异或"运算结果

实例16:用P0显示左移运算结果

实例17:"万能逻辑电路"实验

实例18:用右移运算流水点亮P1口8位LED

实例19:用if语句控制P0口8位LED的流水方向

实例20:用swtich语句的控制P0口8位LED的点亮状态

实例21:用for语句控制蜂鸣器鸣笛次数

实例22:用while语句控制LED

实例23:用do-while语句控制P0口8位LED流水点亮

实例24:用字符型数组控制P0口8位LED流水点亮

实例25: 用P0口显示字符串常量

实例26:用P0 口显示指针运算结果

实例27:用指针数组控制P0口8位LED流水点亮

实例28:用数组的指针控制P0 口8 位LED流水点亮

实例29:用P0 、P1口显示整型函数返回值

实例30:用有参函数控制P0口8位LED流水速度

实例31:用数组作函数参数控制流水花样

实例32:用指针作函数参数控制P0口8位LED流水点亮

实例33:用函数型指针控制P1口灯花样

实例34:用指针数组作为函数的参数显示多个字符串

单片机c语言编程100个实例目录2

实例35:字符函数ctype.h应用举例

实例36:内部函数intrins.h应用举例

实例37:标准函数stdlib.h应用举例

实例38:字符串函数string.h应用举例

实例39:宏定义应用举例2

实例40:宏定义应用举例2

实例41:宏定义应用举例3

* 中断、定时器中断、定时器 *中断、定时器*中断、定时器 /

实例42:用定时器T0查询方式P2口8位控制LED闪烁

实例43:用定时器T1查询方式控制单片机发出1KHz音频

实例44:将计数器T0计数的结果送P1口8位LED显示

实例45:用定时器T0的中断控制1位LED闪烁

实例46:用定时器T0的中断实现长时间定时

实例47:用定时器T1中断控制两个LED以不同周期闪烁

实例48:用计数器T1的中断控制蜂鸣器发出1KHz音频

实例49:用定时器T0的中断实现"渴望"主题曲的播放

实例50-1:输出50个矩形脉冲

实例50-2:计数器T0统计外部脉冲数

实例51-2:定时器T0的模式2测量正脉冲宽度

实例52:用定时器T0控制输出高低宽度不同的矩形波

实例53:用外中断0的中断方式进行数据采集

实例54-1:输出负脉宽为200微秒的方波

实例54-2:测量负脉冲宽度

实例55:方式0控制流水灯循环点亮

实例56-1:数据发送程序

实例56-2:数据接收程序

实例57-1:数据发送程序

实例57-2:数据接收程序

实例58:单片机向PC发送数据

实例59:单片机接收PC发出的数据

*数码管显示*数码管显示 数码管显示数码管显示*/

实例60:用LED数码显示数字5

实例61:用LED数码显示器循环显示数字0~9

实例62:用数码管慢速动态扫描显示数字"1234"

实例63:用LED数码显示器伪静态显示数字1234

实例64:用数码管显示动态检测结果

实例65:数码秒表设计

实例66:数码时钟设计

实例67:用LED数码管显示计数器T0的计数值

实例68:静态显示数字“59”

单片机c语言编程100个实例目录3

键盘控制*键盘控制* *键盘控制 *键盘控制 */

实例69:无软件消抖的独立式键盘输入实验

实例70:软件消抖的独立式键盘输入实验

实例71:CPU控制的独立式键盘扫描实验

实例72:定时器中断控制的独立式键盘扫描实验

实例73:独立式键盘控制的4级变速流水灯

实例74:独立式键盘的按键功能扩展:"以一当四"

实例75:独立式键盘调时的数码时钟实验

实例76:独立式键盘控制步进电机实验

实例77:矩阵式键盘按键值的数码管显示实验

//实例78:矩阵式键盘按键音

实例79:简易电子琴

实例80:矩阵式键盘实现的电子密码锁

液晶显示LCD*液晶显示LCD *液晶显示LCD * *液晶显示LCD*液晶显示LCD *液晶显示LCD */

实例81:用LCD显示字符'A'

实例82:用LCD循环右移显示"Welcome to China"

实例83:用LCD显示适时检测结果

实例84:液晶时钟设计

*一些芯片的使用*24c02 DS18B20 X5045 ADC0832 DAC0832 DS1302 红外遥控/

实例85:将数据"0x0f"写入AT24C02再读出送P1口显示

实例86:将按键次数写入AT24C02,再读出并用1602LCD显示

实例87:对I2C总线上挂接多个AT24C02的读写操作

实例88:基于AT24C02的多机通信 读取程序

实例89:基于AT24C02的多机通信 写入程序

实例90:DS18B20温度检测及其液晶显示

实例91:将数据"0xaa"写入X5045再读出送P1口显示

实例92:将流水灯控制码写入X5045并读出送P1口显示

实例93:对SPI总线上挂接多个X5045的读写操作

实例94:基于ADC0832的数字电压表

实例95:用DAC0832产生锯齿波电压

实例96:用P1口显示红外遥控器的按键值

实例97:用红外遥控器控制继电器

实例98:基于DS1302的日历时钟

实例99:单片机数据发送程序

实例100:电机转速表设计

模拟霍尔脉冲

单片机c语言一百例子

汇编代码实例

伪 指 令

伪指令是对汇编起某种控制作用的特殊命令,其格式与通常的操作指令一样,并可加在汇编程序的任何地方,但它们并不产生机器指令。许多伪指令要求带参数,这在定义伪指令时由“表达式”域指出,任何数值与表达式匀可以作为参数。不同汇编程序允许的伪指令并不相同,以下所述的伪指令仅适用于MASM51系统,但一些基本的伪指令在大部份汇编程序中都能使用,当使用其它的汇编程序版本时,只要注意一下它们之间的区别就可以了。MASM51中可用的伪指令有:ORG 设置程序起始地址END 标志源代码结束EQU 定义常数SET 定义整型数DATA 给字节类型符号定值BYTE 给字节类型符号定值WROD 给字类型符号定值BIT 给位地址取名ALTNAME 用自定义名取代保留字DB 给一块连续的存储区装载字节型数据DW 给一块连续的存储区装载字型数据DS 预留一个连续的存储区或装入指定字节。INCLUDE 将一个源文件插入程序中TITLE 列表文件中加入标题行NOLIST 汇编时不产生列表文件NOCODE 条件汇编时,条件为假的不产生清单一、ORG 伪指令ORG用于为在它之后的程序设置地址值,它有一个参数,其格式为:ORG 表达式表达式可以是一个具体的数值,也可以包含变量名,如果包含变量名,则必须保证,当第一次遇到这条伪指令时,其中的变量必须已有定义(已有具体的数值),否则,无定义的值将由0替换,这将会造成错误。在列表文件中,由ORG定义的指令地址会被打印出来。ORG指令有什么用途呢?指令被翻译成机器码后,将被存入系统的ROM中,一般情况下,机器码总是一个接一个地放在存储器中,但有一些代码,其位置有特殊要求,典型的是五个中断入口,它们必须被放在0003H,000BH,0013H,001BH和0023H的位置,否则就会出错,如果我们编程时不作特殊处理,让机器代码一个接一个地生成,不能保证这些代码正好处于这些规定的位置,执行就会出错,这时就要用到ORG伪指令了。看如下例子:例:INT_0 EQU 1000HTIME_0 EQU 1010HINT_1 EQU 1020HTIME_1 EQU 1030HSERIAL EQU 1040HAJMP START ;跳转到主程序起始点LJMP INT_0 ;外中断0处理程序LJMP TIME_0 ;定时中断0处理程序LJMP INT_1 ;外中断1处理程序LJMP TIME_1 ;定时中断1处理程序LJMP SERIAL ;串行口中断程序START:NOPEND上面的程序经汇编后列表文件如下:The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 108-26-96  1000 = INT_0 EQU 1000H1010 = TIME_0 EQU 1010H1020 = INT_1 EQU 1020H1030 = TIME_1 EQU 1030H1040 = SERIAL EQU 1040H0000 0111 AJMP START ;跳转到主程序起始点0002 021000 LJMP INT_0 ;外中断0处理程序0005 021010 LJMP TIME_0 ;定时中断0处理程序0008 021020 LJMP INT_1 ;外中断1处理程序000B 021030 LJMP TIME_1 ;定时中断1处理程序000E 021040 LJMP SERIAL ;串行口中断程序START:0011 00 NOP0000 ENDThe Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 208-26-96;%T Symbol Name Type ValueINT_0 . . . . . . . . . . . . . I 1000INT_1 . . . . . . . . . . . . . I 1020SERIAL. . . . . . . . . . . . . I 1040START . . . . . . . . . . . . . L 0011TIME_0. . . . . . . . . . . . . I 1010TIME_1. . . . . . . . . . . . . I 1030;%Z00 Errors (0000)由列表文件,可以绘出代码在ROM中的映象图如下:代码

01H

11H

02H

10H

00H

02H

10H

10H

02H

10H

20H

地址

00H

01H

02H

03H

04H

05H

06H

07H

08H

09H

0AH

代码

02H

10H

30H

02H

10H

40H

00H

 

 

 

 

地址

0BH

0CH

0DH

0EH

0FH

10H

11H

12H

13H

14H

15

由上面的映象图可知,在03H处的代码为10H,而不是我们要的02H,所以外断程序INT_0不能被正确执行,其它各中断程序的情况同样如此,如在0BH处,本来存放的应当是定时器0中断程序,但按上述的映象图,0BH处开始的3个代码是:02H,10H,30H,这是定时器1的入口地址,所以,如果定时器0发生中断,所执行的其实是定时器1的中断程序,这当然不对。例2:INT_0 EQU 1000HTIME_0 EQU 1010HINT_1 EQU 1020HTIME_1 EQU 1030HSERIAL EQU 1040HAJMP START ;跳转到主程序起始点ORG 0003HLJMP INT_0 ;外中断0处理程序ORG 000BHLJMP TIME_0 ;定时中断0处理程序ORG 0013HLJMP INT_1 ;外中断1处理程序ORG 001BHLJMP TIME_1 ;定时中断1处理程序ORG 0023HLJMP SERIAL ;串行口中断程序START:NOPEND上面的程序经过汇编后列表文件如下:The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 108-26-961000 = INT_0 EQU 1000H1010 = TIME_0 EQU 1010H1020 = INT_1 EQU 1020H1030 = TIME_1 EQU 1030H1040 = SERIAL EQU 1040H0000 0126 AJMP START ;跳转到主程序起始点0003 ORG 0003H0003 021000 LJMP INT_0 ;外中断0处理程序000B ORG 000BH000B 021010 LJMP TIME_0 ;定时中断0处理程序0013 ORG 0013H0013 021020 LJMP INT_1 ;外中断1处理程序001B ORG 001BH001B 021030 LJMP TIME_1 ;定时中断1处理程序0023 ORG 0023H0023 021040 LJMP SERIAL ;串行口中断程序START:0026 00 NOP0000 ENDThe Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 208-26-96;%T Symbol Name Type ValueINT_0 . . . . . . . . . . . . . I 1000INT_1 . . . . . . . . . . . . . I 1020SERIAL. . . . . . . . . . . . . I 1040START . . . . . . . . . . . . . L 0026TIME_0. . . . . . . . . . . . . I 1010TIME_1. . . . . . . . . . . . . I 1030;%Z00 Errors (0000)由列表文件,可以绘出代码在ROM中的映象图如下:代码

01H

11H

 

02H

10H

00H

 

 

 

 

 

地址

00H

01H

02H

03H

04H

05H

06H

07H

08H

09H

0AH

代码

02H

10H

10H

 

 

 

 

 

02H

01H

20H

地址

0BH

0CH

0DH

0EH

0FH

10H

11H

12H

13H

14H

15H

代码

 

 

 

 

02H

10H

30H

 

 

 

地址

16H

17H

18H

19H

1AH

1BH

1CH

1DH

1EH

1FH

20H

代码

 

 

02H

10H

40H

00H

 

 

 

 

 

地址

21H

22H

23H

24H

25H

26H

27H

28H

29H

2AH

2BH

由映象图可知,各中断程序的代码都在其规定地址处,一旦产生中断即可执行相应的程序。至于图中未填的部分(如02H),根据各编程器不同而不同,一般为FFH或00H。 二、END END语句标志源代码的结束,汇编程序遇到END语句即停止运行。若没有END语句,汇编将报错。END语句有一个参数,可以是数值0,也可以是表达式,其格式是:标号: END 表达式它的值就是程序的地址并且作为一个特殊的记录写入HEX文件。若这个表达式省略,HEX文件中其值就是0。三、EQU EQU以及其它一些符号定义伪指令用来给程序中出现的一些符号赋值。对这些符号名的要求与其它符号相同,即长度不限,大小写字母可互换并且必须以字母开头。由等值指令定义的符号是汇编符号表的一部分。等值伪指令有两种形式。一种用EQU,另一种用字符“=”即符号名 EQU 表达式符号名 = 表达式两种形式的效果是一样的。符号名在左边,其对应的值在右边。值可以是变元,其它的符号名或表达式。只要在两遍扫描中求出表达式的值就行,否则引用该符号名时将报错。当表达式的值是字符串时,只取后两个字符。若串长为1,高位字节被置0,符号名的值被打印在程序清单中。由等值伪指令定义的符号名不允许重名。如果经定义的符号名被重定义,则汇编将报出错,并且这个符号名按新定义的处理,最好不要在程序中出现重名。例:0469= ABC EQU 469H0464= XY EQU ABC-502F0= JK = 7520754 XYJK = XY+JK在列表文件中最左边的数字不是这些伪指令所在的地址而是通过汇编后赋给符号名的值。第一条符号名ABC被起来469H,第二条XY被赋于ABC-5,因此XY的值为469H-5=464H,JK的值为752(即2F0H),XYJK的值XY+JK=464H+2F0H=754H四、SET SET伪指令有些类似于等值伪指令,它定义了一个整数类型的符号名,它的格式为符号名 SET 表达式SET伪指令与等值伪指令的唯一区别在于SET伪指令所定义的符号名右以在程序中多次定义,而不报错。例:002D= K57 SET 101101B8707= K57 SET 34567五、DATA与BYTE DATA与BYTE都是用来定义字节类型的存储单元,赋予字节类型的存储单元一个符号名,以便在程序中通过符号名来访问这个存储单元,以帮助对程序的理解。BYTE与DATE之间的区别类似于EQU和SET,BYTE伪指令不能定义重名。六、WORD WORD伪指令类似于DATE伪指令,只是WORD伪指令定义了一个字类型的符号名,其格式为:符号名 WORD 表达式0027= VAL31 WORD 390021= PAR7 WORD 21H一个字由2个字节组成。当然,因为8051汇编语言集没有字操作,所以程序执行时,只处理字节。WROD伪指令仅仅允许用户定义一个认为是字的存储位置。七、BIT BIT伪指令定义了一个字位类型的符号名,其格式为:符号名 BIT 表达式这里表达式的值是一个位地址,这个伪指令有助于位的地址符号化。例:002F= LOG3 BIT 470014= Y731 BIT 14H八、ALTNAME 替换名(ALTNAME)伪指令提供用户一种手段,以定义一个符号名来替换一个保留字,此后这个答名与被替换的保留字均可等效地用于程序中。任何保留类型的答名均可被替换。替换名伪指令格式为:ALTNAME 保留字,新名例:0002= ALTNAME R2 COUNT013A EA MOV A,R2013B E502 MOV A,COUNT九、DB DB伪指令用于定义一个连续的存储区,给该存储区的存储单元赋值。该伪指令的参数即为存储单元的值,在表达式中对变元个数没有限制,只要此条伪指令能容纳在源程序的一行内,其格式为:标号: DB 表达式只要表达式不是字符串,每一表达式值都被赋给一个字节。计算表达式值时按16位处理,但其结果只取低8位,若多个表达式出现在一个DB伪指令中,它们必须以逗号分开。表达式中有字符串时,以单引号“'”作分隔符,每个字符占一个字节,字符串不加改变地被存在各字节中,并不将小写字母转换成大写字母。例如:DB 00H 01H 03H 46HDB 'This is a demo!'十、DW DW为以字节为单元(十六位二进制)来给一个的存储区赋值,其格式为:标号: DW 表达式例如:0000 3035 D46B DW 12341,54379,10110100101110B0004 2D2E0006 4344 4243 DW 'ABCD','BC','A'000A 0041000C 2868 02E8 DW 456*375h,83+295h,'YZ',72h-4560010 595A FEAA十一、DS DS为定义存储内容的伪指令,用它定义一个存储区,并用指定的参数填满该存储区。DS伪指令包含两个变元,第一个变元定义了存储区的长度的字节数,在汇编时,汇编程序将跳过这些单元把其它指令汇编在这些字节之后,因此在使用DS伪指令时第一个变元不可活力第二个变元表示在这些单元中真入什么值,第二个变元可以活力活力时这些字节将不处理。下例中0173处有一条DS 9,则空出9个字节,下一第指令被汇编到017C处;在017C处空出1BH个单元,在这些字节中被27H所填充。DS指令的格式如下:标号: DS 表达式1,表达式2表达式1定义了存储区的长度(以字节为单位)。这个变元不能省略。表达式2是可选择的,它的值低8位用以填入所定义的存储区。若省略则这部分存储单元不处理。例:0000 04 INC A0001 DS 9000A 04 INC A000B DS 1BH,27H0026 04 INC A十二、INCLUDE INCLUDE伪指令用于链接源文件,即将一个源文件插入到另一个源文件中。它有一个参数,指出将要插入的文件名,该文件名中可包括驱动器名和路径名。若文件没有扩展名,则默认为是ASM。但待插入的文件必须是可以打开的。若文件打开操作失败,则产生致命错误,汇编将停止运行。反之,汇编程序将文件内容读入并按源代码处理。当遇到文件结速符时,汇编程序返回到INCLUDE伪指令处继续身下处理源程序。被插入的文件在程序清单中以“I”开头。本宏汇编版本支持级嵌套,可在程序中用INCLUDE伪指令插入任意多个文件,但是,在一般情况下DOS允许打开的文件数量是有限的,如果用户需要打开较多的文件,则必须在CONFIG.SYS文件中加入FILES=40或更多的值,若超过8级嵌套或打开的文件太多,则产生致命错误,汇编中止运行。INCLUDE伪指令提供了模块化程序设计手段,在汇编程序处理主程序时,模块被插入,尽管这不等价于链接和装配可重定位的目标模块,但它具有类似的功能,被插入的源文件中不应该包含END伪指令,否则,汇编就会提前停止运行,END伪指令只能出现在主程序中。此外,在主程序进行汇编前所有附加的源文件必须通过汇编,产生相应的HEX及LST文件,由于附加的文件没有END伪指令,因此,附加文件汇编时,汇编程序将显示:“没有结束语句”的错误,但并不影响与主程序的链接。下面是一个使用INCLUDE伪指令的例子,其主程序的源文件MAIN.ASM为:;MAIN.ASMORG 27HSTART:CLR AMOV R3,AINCLUDE MOD1INC R5INCLUDE MOD2.ASMDEC R3END START主程序为带有END伪指令的完整的源文件。程序中有两INCLUDE伪指令,分别将两附加的文件MOD1.ASM及MOD2.ASM链接到主程序中。以下是这两个文件。;MOD1.ASMMOV R2,#31HMOV R5,#18H;MOD2.ASMMOV R6,#47HANL A,#07HMOV R1,A注意MOD1.ASM及MOD2.ASM均没有END指令。在进行汇编时必须先对MOD1.ASM和MOD2.ASM进行汇编,然后在汇编MAIN.ASM,由于上两个文件没有END伪指令,所以在汇编时会出现错误提示,不用管它,继续下面的工作,就可以得到正确的结果。以下是形成的列表文件:The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1;MOD2.ASMMOV R6,#47HANL A,#07HMOV R1,A08-27-96;MAIN.ASM0027 ORG 27HSTART:0027 E4 CLR A0028 FB MOV R3,AI INCLUDE MOD1I ;MOD1.ASMI0029 7A31 MOV R2,#31HI002B 7D18 MOV R5,#18HI002D 0D INC R5I INCLUDE MOD2.ASMI ;MOD2.ASMI002E 7E47 MOV R6,#47HI0030 5407 ANL A,#07HI0032 F9 MOV R1,A0033 1B DEC R30027 END STARTThe Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 208-27-96;%T Symbol Name Type ValueSTART . . . . . . . . . . . . . L 0027;%Z00 Errors (0000)十三、TITL TITLE伪指令用于在列表文件页头建立一个标题,其格式为:$TITLE 标题行这里标量行就是将出现在页头的标量与通常的字符串定义不同。这里标量行不加引号。汇编从$TITLE之后的第一个可打印字符开始,到回车符之间的字符串作为标量标量的最大长度是60个字符,基标量行省略,则标题行为空行。若TITLE伪指令在一页,它说明的标量行包含在本页,否则,标题将出现在下页页头。十四、PAGE PAGE伪指令用于形成新的一中定义一面的行数。其格式为:$PAGE 表达式若表达 式缺省则开始新的一页,若有表达式,则每页行数重新定义。汇编开始时页长为66行。一页中除出页外,剩余55行用于打印源程序,这一格式适用于标准打印纸。如果变元值小于66,页内可打印的源代码行将相应减少。页长最小值为12。若小于12时,每页内除页上只打印一行源程序。页长变元是16位字节,因而每页最长可定义到65535行,这时分页打印变为连续打印,在屏幕显示程序清单或在卷筒纸上打印程序清单时,常常使用连续打印,如果在启动汇编时用/N选项,页长就是65535。十五、LIST与NOLIST 它们的格式为:$LIST$NOLISTLIST伪指令使汇编时主生程序清单,但即使不用该指令,汇编也会自动产生清单。但如果使用了NOLIST伪指令后需要继续主生清单则必须使用LIST伪指令。NOLIST伪指令使汇编时不产生清单,所有包含此伪指令及在这条伪指令之后的语句都不进入列表文件。当不需要任何列表文件,并且不需要显示程序清单时,可以在启动汇编时不加.L附加项,且在源代码的第一行加上NOLIST指令。使用NOLIST伪指令与附加项/L不同之处是NOLIST伪指令可加在源程序中,与LIST伪指令配合使用,使源程序中某些部分不产生清单。而不加附加项/L则不产生任何程序清单。不过,不管有无$NOLIST伪指令,程序在汇编时检查到的错误都将在屏幕上显示出错的源代码行及错误信息十六、NOCODE 其格式为 $NOCODENOCODE伪指令使得在汇编时,条件汇编程序结构中那些真值为假的条件不产生清单。有关条件汇编结构在下面介绍。如果没有这条伪指令,汇编将主生所有条件下的清单,不论其真值是否为真。但是假的条件,不产生目标码。而NOCODE伪指令使汇编清单中只列出那些由汇编程序用到的部分,因此,当使用NOCODE伪指令时,程序清单与源程序并非逐行对应。 本文来自CSDN博客,转载请标明出处:

求java工厂模式的一个简单代码例子,尽量简单

这个应该比较简单一点。

某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等,且用户可以根据要求动态选择日志记录方式。现使用工厂方法模式设计该系统,并写出相应Java代码。

interface Log{

    public void writeLog();

}

class FileLog implements Log{

    public void writeLog(){

        System.out.println("文件记录");

    }

}

class DatabaseLog implements Log{

    public void writeLog(){

        System.out.println("数据库记录");

    }

}

interface LogFactory{

    public Log createLog();

}

class FileLogFactory implements LogFactory{

    public Log createLog(){

        return new FileLog();

    }

}

class DatabaseLogFactory implements LogFactory{

    public Log createLog(){

        return new DatabaseLog();

    }

}

public class Client{

    public static void main(String[] args) {

        try{

            Log log;

            LogFactory factory;

//这里可以改成使用DOM和Java反射机制读取XML文件,获取工厂类名

            factory=new DatabaseLogFactory ();

            log=factory.createLog();

            log.writeLog();

        }

        catch(Exception e){

            System.out.println(e.getMessage());

        }

    }

}

常见代码重构技巧(非常实用)

1_代码重构漫画.jpeg

项目在不断演进过程中,代码不停地在堆砌。如果没有人为代码的质量负责,代码总是会往越来越混乱的方向演进。当混乱到一定程度之后,量变引起质变,项目的维护成本已经高过重新开发一套新代码的成本,想要再去重构,已经没有人能做到了。

造成这样的原因往往有以下几点:

对于此类问题,业界已有有很好的解决思路:通过持续不断的重构将代码中的“坏味道”清除掉。

重构一书的作者Martin Fowler对重构的定义:

根据重构的规模可以大致分为大型重构和小型重构:

大型重构 :对顶层代码设计的重构,包括:系统、模块、代码结构、类与类之间的关系等的重构,重构的手段有:分层、模块化、解耦、抽象可复用组件等等。这类重构的工具就是我们学习过的那些设计思想、原则和模式。这类重构涉及的代码改动会比较多,影响面会比较大,所以难度也较大,耗时会比较长,引入bug的风险也会相对比较大。

小型重构 :对代码细节的重构,主要是针对类、函数、变量等代码级别的重构,比如规范命名和注释、消除超大类或函数、提取重复代码等等。小型重构更多的是使用统一的编码规范。这类重构要修改的地方比较集中,比较简单,可操作性较强,耗时会比较短,引入bug的风险相对来说也会比较小。什么时候重构 新功能开发、修bug或者代码review中出现“代码坏味道”,我们就应该及时进行重构。持续在日常开发中进行小重构,能够降低重构和测试的成本。

2_代码常见问题.png

代码重复

方法过长

过大的类

逻辑分散

严重的情结依恋

数据泥团/基本类型偏执

不合理的继承体系

过多的条件判断

过长的参数列

临时变量过多

令人迷惑的暂时字段

纯数据类

不恰当的命名

过多的注释

3_代码质量如何衡量.jpg

代码质量的评价有很强的主观性,描述代码质量的词汇也有很多,比如可读性、可维护性、灵活、优雅、简洁。这些词汇是从不同的维度去评价代码质量的。其中,可维护性、可读性、可扩展性又是提到最多的、最重要的三个评价标准。

要写出高质量代码,我们就需要掌握一些更加细化、更加能落地的编程方法论,这就包含面向对象设计思想、设计原则、设计模式、编码规范、重构技巧等。

4_SOLID原则.png

一个类只负责完成一个职责或者功能,不要存在多于一种导致类变更的原因。

单一职责原则通过避免设计大而全的类,避免将不相关的功能耦合在一起,来提高类的内聚性。同时,类职责单一,类依赖的和被依赖的其他类也会变少,减少了代码的耦合性,以此来实现代码的高内聚、松耦合。但是,如果拆分得过细,实际上会适得其反,反倒会降低内聚性,也会影响代码的可维护性。

添加一个新的功能,应该是通过在已有代码基础上扩展代码(新增模块、类、方法、属性等),而非修改已有代码(修改模块、类、方法、属性等)的方式来完成。

开闭原则并不是说完全杜绝修改,而是以最小的修改代码的代价来完成新功能的开发。

很多设计原则、设计思想、设计模式,都是以提高代码的扩展性为最终目的的。特别是 23 种经典设计模式,大部分都是为了解决代码的扩展性问题而总结出来的,都是以开闭原则为指导原则的。最常用来提高代码扩展性的方法有:多态、依赖注入、基于接口而非实现编程,以及大部分的设计模式(比如,装饰、策略、模板、职责链、状态)。

子类对象(object of subtype/derived class)能够替换程序(program)中父类对象(object of base/parent class)出现的任何地方,并且保证原来程序的逻辑行为(behavior)不变及正确性不被破坏。

子类可以扩展父类的功能,但不能改变父类原有的功能

调用方不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。接口隔离原则提供了一种判断接口的职责是否单一的标准:通过调用者如何使用接口来间接地判定。如果调用者只使用部分接口或接口的部分功能,那接口的设计就不够职责单一。

高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。

一个对象应该对其他对象保持最少的了解

尽量使用合成/聚合的方式,而不是使用继承。

单一职责原则告诉我们实现类要职责单一;里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合。而开闭原则是总纲,告诉我们要对扩展开放,对修改关闭。

image.png

模块结构说明

代码开发要遵守各层的规范,并注意层级之间的依赖关系。

多个方法代码重复、方法中代码过长或者方法中的语句不在一个抽象层级。

方法是代码复用的最小粒度,方法过长不利于复用,可读性低,提炼方法往往是重构工作的第一步。

意图导向编程 :把处理某件事的流程和具体做事的实现方式分开。

将函数放进一个单独对象中,如此一来局部变量就变成了对象内的字段。然后你可以在同一个对象中将这个大型函数分解为多个小型函数。

方法参数比较多时,将参数封装为参数对象

任何有返回值的方法,都不应该有副作用

临时变量仅使用一次或者取值逻辑成本很低的情况下

将复杂表达式(或其中一部分)的结果放进一个临时变量,以此变量名称来解释表达式用途

把复杂的条件表达式拆分成多个条件表达式,减少嵌套。嵌套了好几层的if - then-else语句,转换为多个if语句

当出现大量类型检查和判断时,if else(或switch)语句的体积会比较臃肿,这无疑降低了代码的可读性。 另外,if else(或switch)本身就是一个“变化点”,当需要扩展新的类型时,我们不得不追加if else(或switch)语句块,以及相应的逻辑,这无疑降低了程序的可扩展性,也违反了面向对象的开闭原则。

非正常业务状态的处理,使用抛出异常的方式代替返回错误码

某一段代码需要对程序状态做出某种假设,以断言明确表现这种假设。

当使用一个方法返回的对象时,而这个对象可能为空,这个时候需要对这个对象进行操作前,需要进行判空,否则就会报空指针。当这种判断频繁的出现在各处代码之中,就会影响代码的美观程度和可读性,甚至增加Bug的几率。

空引用的问题在Java中无法避免,但可以通过代码编程技巧(引入空对象)来改善这一问题。

根据单一职责原则,一个类应该有明确的责任边界。但在实际工作中,类会不断的扩展。当给某个类添加一项新责任时,你会觉得不值得分离出一个单独的类。于是,随着责任不断增加,这个类包含了大量的数据和函数,逻辑复杂不易理解。

此时你需要考虑将哪些部分分离到一个单独的类中,可以依据高内聚低耦合的原则。如果某些数据和方法总是一起出现,或者某些数据经常同时变化,这就表明它们应该放到一个类中。另一种信号是类的子类化方式:如果你发现子类化只影响类的部分特性,或者类的特性需要以不同方式来子类化,这就意味着你需要分解原来的类。

继承使实现代码重用的有力手段,但这并非总是完成这项工作的最佳工具,使用不当会导致软件变得很脆弱。与方法调用不同的是,继承打破了封装性。子类依赖于其父类中特定功能的实现细节,如果父类的实现随着发行版本的不同而变化,子类可能会遭到破坏,即使他的代码完全没有改变。

举例说明,假设有一个程序使用HashSet,为了调优该程序的性能,需要统计HashSet自从它创建以来添加了多少个元素。为了提供该功能,我们编写一个HashSet的变体。

通过在新的类中增加一个私有域,它引用现有类的一个实例,这种设计被称为组合,因为现有的类变成了新类的一个组件。这样得到的类将会非常稳固,它不依赖现有类的实现细节。即使现有的类添加了新的方法,也不会影响新的类。许多设计模式使用就是这种套路,比如代理模式、装饰者模式

继承与组合如何取舍

Java提供了两种机制,可以用来定义允许多个实现的类型:接口和抽象类。自从Java8为接口增加缺省方法(default method),这两种机制都允许为实例方法提供实现。主要区别在于,为了实现由抽象类定义的类型,类必须称为抽象类的一个子类。因为Java只允许单继承,所以用抽象类作为类型定义受到了限制。

接口相比于抽象类的优势:

接口虽然提供了缺省方法,但接口仍有有以下局限性:

接口缺省方法的设计目的和优势在于:

为了接口的演化

可以减少第三方工具类的创建

可以避免创建基类

由于接口的局限性和设计目的的不同,接口并不能完全替换抽象类。但是通过对接口提供一个抽象的骨架实现类,可以把接口和抽象类的优点结合起来。 接口负责定义类型,或许还提供一些缺省方法,而骨架实现类则负责实现除基本类型接口方法之外,剩下的非基本类型接口方法。扩展骨架实现占了实现接口之外的大部分工作。这就是模板方法(Template Method)设计模式。

Image [5].png

接口Protocol:定义了RPC协议层两个主要的方法,export暴露服务和refer引用服务

抽象类AbstractProtocol:封装了暴露服务之后的Exporter和引用服务之后的Invoker实例,并实现了服务销毁的逻辑

具体实现类XxxProtocol:实现export暴露服务和refer引用服务具体逻辑

由于为了保持Java代码的兼容性,支持和原生态类型转换,并使用擦除机制实现的泛型。但是使用原生态类型就会失去泛型的优势,会受到编译器警告。

每一条警告都表示可能在运行时抛出ClassCastException异常。要尽最大的努力去消除这些警告。如果无法消除但是可以证明引起警告的代码是安全的,就可以在尽可能小的范围中,使用@SuppressWarnings("unchecked")注解来禁止警告,但是要把禁止的原因记录下来。

参数化类型不支持协变的,即对于任何两个不同的类型Type1和Type2而言,List既不是List的子类型,也不是它的超类。为了解决这个问题,提高灵活性,Java提供了一种特殊的参数化类型,称作有限制的通配符类型,即List? extends E和List? super E。使用原则是producer-extends,consumer-super(PECS)。如果即是生产者,又是消费者,就没有必要使用通配符了。

还有一种特殊的无限制通配符List?,表示某种类型但不确定。常用作泛型的引用,不可向其添加除Null以外的任何对象。

嵌套类(nested class)是指定义在另一个类的内部的类。 嵌套类存在的目的只是为了它的外部类提供服务,如果其他的环境也会用到的话,应该成为一个顶层类(top-level class)。 嵌套类有四种:静态成员类(static member class)、非静态成员类(nonstatic member class)、匿名类(anonymous class)和 局部类(local class)。除了第一种之外,其他三种都称为内部类(inner class)。

总而言之,这四种嵌套类都有自己的用途。假设这个嵌套类属于一个方法的内部,如果只需要在一个地方创建实例,并且已经有了一个预置的类型可以说明这个类的特征,就要把它做成匿名类。如果一个嵌套类需要在单个方法之外仍然可见,或者它太长了,不适合放在方法内部,就应该使用成员类。如果成员类的每个实例都需要一个指向其外围实例的引用,就要把成员类做成非静态的,否则就做成静态的。

通过对常见场景的代码逻辑进行抽象封装,形成相应的模板工具类,可以大大减少重复代码,专注于业务逻辑,提高代码质量。

面向对象编程相对于面向过程,多了实例化这一步,而对象的创建必须要指定具体类型。我们常见的做法是“哪里用到,就在哪里创建”,使用实例和创建实例的是同一段代码。这似乎使代码更具有可读性,但是某些情况下造成了不必要的耦合。

对于顶层的(非嵌套的)类和接口,只有两种的访问级别:包级私有的(没有public修饰)和公有的(public修饰)。

对于成员(实例/域、方法、嵌套类和嵌套接口)由四种的访问级别,可访问性如下递增:

正确地使用这些修饰符对于实现信息隐藏是非常关键的,原则就是:尽可能地使每个类和成员不被外界访问(私有或包级私有)。这样好处就是在以后的发行版本中,可以对它进行修改、替换或者删除,而无须担心会影响现有的客户端程序。

不可变类是指其实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例时提供,并在对象的整个生命周期内固定不变。不可变类好处就是简单易用、线程安全、可自由共享而不容易出错。Java平台类库中包含许多不可变的类,比如String、基本类型包装类、BigDecimal等。

为了使类成为不可变,要遵循下面五条规则:

可变性最小化的一些建议:

TDD的最终目标是整洁可用的代码(clean code that works)。大多数的开发者大部分时间无法得到整洁可用的代码。办法是分而治之。首先解决目标中的“可用”问题,然后再解决“代码的整洁”问题。这与体系结构驱动(architecture-driven)的开发相反。

采用TDD另一个好处就是让我们拥有一套伴随代码产生的详尽的自动化测试集。将来无论出于任何原因(需求、重构、性能改进)需要对代码进行维护时,在这套测试集的驱动下工作,我们代码将会一直是健壮的。

Image [6].png

添加一个测试 - 运行所有测试并检查测试结果 - 编写代码以通过测试 - 运行所有测试且全部通过 - 重构代码,以消除重复设计,优化设计结构

作者:VectorJin

ASP网页程序设计中10个非常有用的实例代码

ASP网页程序设计中10个非常有用的实例代码

ASP可以与Web数据库以及其它程序进行交互,是一种简单、方便的编程工具。下面由我带来ASP网页程序设计中10个非常有用的实例代码。

1.如何用Asp判断你的网站的.虚拟物理路径

答:使用Mappath方法: %= Server.MapPath("\")%

2.我如何知道使用者所用的浏览器

答:使用the Request object方法:

3.如何计算每天的平均反复访问人数

答:解决方法

% startdate=DateDiff("d",Now,"01/01/1990")

if strdate 0 then startdate=startdate*-1

avgvpd=Int((usercnt)/startdate) %

显示结果

% response.write(avgvpd) %

that is it.this page have been viewed since November 10,1998

4.如何显示随机图象

% dim p,ppic,dpic

ppic=12

randomize

p=Int((ppic*rnd)+1)

dpic="graphix/randompics/"p".gif"

%

显示

img src=" %=dpic% "

5.如何回到先前的页面

答: a href=" %=request.serverVariables("Http_REFERER")% " preivous page /a

或用图片如: img src="arrowback.gif" alt=" %=request.serverVariables("HTTP_REFERER")% "

6.如何确定对方的IP地址

答: %=Request.serverVariables("REMOTE_ADDR)%

7.如何链结到一副图片上

答: % @Languages=vbscript %

% response.expires=0

strimagename="graphix/errors/erroriamge.gif"

response.redirect(strimagename)

%

8.强迫输入密码对话框

答:把这句话放载页面的开头

% response.status="401 not Authorized"

response.end

%

9.如何传递变量从一页到另一页

答:用 HIDDEN 类型来传递变量

% for each item in request.form %

input namee=" %=item% " type="HIDDEN"

value=" %=server.HTMLEncode(Request.form(item)) % "

% next %

/form

10.怎样才能使得htm文件如同asp文件一样可以执行脚本代码

答:Internet Sevices Manager - 选择default web site - 右鼠键- 菜单属性-〉主目录- 应用程序设置(Application Setting)- 点击按钮 "配置"- app mapping - 点击按钮"Add" - executable browse选择 \WINNT\SYSTEM32\INETSRV\ASP.DLL EXTENSION 输入 htm method exclusions 输入PUT.DELETE 全部确定即可。但是值得注意的是这样对htm也要由asp.dll处理,效率将降低。

;

关于代码设计实例和代码编程实例的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

版权说明:如非注明,本站文章均为 AH站长 原创,转载请注明出处和附带本文链接;

本文地址:http://www.ahzz.com.cn/post/768.html


取消回复欢迎 发表评论:

分享到

温馨提示

下载成功了么?或者链接失效了?

联系我们反馈

立即下载