一,前言

7种结构型设计模式:桥接模式,适配器模式,装饰模式,组合模式,享元模式,外观模式,代理模式上篇我们说了外观模式:提供一个统一接口来访问子系统中的一群接口
外观定义了一个高层接口,让子系统更容易使用开发中我们为一个对象添加新行为通常会采用继承的方式
但通常这样做会导致子类泛滥的结果也就是我们常说的类爆炸,为后续的维护带来不便
本着"开放-关闭"的设计原则,我们希望在不修改原有代码的情况下,为对象赋予新的职责这篇的结构型设计模式就可以做到,它就是装饰模式,也叫做装饰器或装饰者模式

二,装饰模式简介

1,简介:

装饰者模式:动态地将责任附加到对象上,在不修改任何底层代码的情况下,为对象赋予新的职责

2,装饰模式类图:

从类图中我们可以看到:装饰者和被装饰者(组件)拥有相同的接口,所以装饰者能够取代被装饰者装饰者与组件进行组合时,通过对象组合为组件加入新的行为所以装饰者模式能在不创建更多子类的情况下,实现对象功能的拓展这也正是组合的威力所在,多用组合少用继承如果依赖继承,类的行为只能在编译时静态决定,行为来自超类或子类进行覆盖组合可以把装饰器和组件进行混合,而且是在运行时才决定具体行为

3,装饰模式中的角色:

抽象组件(Component)角色:给出一个抽象接口,规范准备接收附加责任的对象。
具体组件(ConcreteComponent)角色:定义一个将要接收附加责任的类。装饰(Decorator)角色:持有一个组件对象(Component)的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(ConcreteDecorator)角色:负责为组件对象赋予新职责。

三,装饰模式场景

我们选取一个比较适合装饰模式的场景来对这个模式进行学习
最后我选择了游戏中为角色添加装备来获得属性加成的例子
那么这篇的主题又回到了大家感兴趣的游戏话题上
我们就来看看"王者荣耀"中孙悟空这个英雄的六神装
ps:这里对英雄和装备属性做了修改,和真实游戏中的属性不一致,望谅解!

我们的场景是这样的:1,创建一个抽象组件Hero(即抽象组件角色),通过继承此类创建具体英雄,此类定义了英雄属性2,通过继承Hero类创建具体英雄(孙悟空),并针对英雄个性化做属性调整3,创建一个抽象装备类Equipment(即抽象装饰角色),继承自组件Hero,通过继承此类创建具体装备,此类需定义装饰新功能的接口,以重写为新的功能供外部调用4,通过继承Equipment类创建具体装备类,此类需持有一个具体英雄(Hero)的引用,重写接口时对此引用信息做修改,以实现功能的变更和添加5,使用4的方式创建6件装备,并逐一为英雄装饰,打印日志查看装饰后的英雄属性

四,装饰模式例子

1,创建抽象组件Hero,即抽象组件角色,定义英雄属性

package com.brave.decorator.pesticide.hero;/*** 抽象英雄*  -每个具体英雄都继承自此类*  -默认属性数值均为100暴击率0%暴击效果2倍* * @author Brave**/
public abstract class Hero {private String name = "";   // 名称private double HP = 100;    // 生命值private double MP = 100;    // 魔法值private double ATK = 100;   // 攻击力private double DEF = 100;   // 防御力private double CRT = 0;     // 暴击率加成private double CRTE = 2;    // 暴击效果private double MS = 0;      // 移动速度加成private double AB = 0;      // 破甲加成private String equipment = "";  // 装备public String getName() {return name;}public void setName(String name) {this.name = name;}public double getHP() {return HP;}public void setHP(double hP) {HP = hP;}public double getMP() {return MP;}public void setMP(double mP) {MP = mP;}public double getATK() {return ATK;}public void setATK(double aTK) {ATK = aTK;}public double getDEF() {return DEF;}public void setDEF(double dEF) {DEF = dEF;}public double getCRT() {return CRT;}public void setCRT(double cRT) {CRT = cRT;}public double getCRTE() {return CRTE;}public void setCRTE(double cRTE) {CRTE = cRTE;}public double getMS() {return MS;}public void setMS(double mS) {MS = mS;}public String getEquipment() {return equipment;}public void setEquipment(String equipment) {this.equipment = equipment;}public double getAB() {return AB;}public void setAB(double aB) {AB = aB;}public void printHeroAttr() {System.out.println("name = " + name);System.out.println("生命值:HP = " + HP);System.out.println("魔法值:MP = " + MP);System.out.println("攻击力:ATK = " + ATK);System.out.println("防御力:DEF = " + DEF);System.out.println("暴击率加成:CRT = " + CRT);System.out.println("暴击效果:CRTE = " + CRTE);System.out.println("移动速度加成:MS = " + MS);if(!equipment.equals(""))System.out.println("装备:equipment = " + equipment);}}

2,通过继承Hero类创建具体英雄孙悟空,针对英雄个性化做属性调整

package com.brave.decorator.pesticide.hero;/*** 具体英雄-孙悟空* 初始暴击率为20%,暴击伤害150%;* * @author Brave**/
public class MonkeyKing extends Hero {public MonkeyKing() {setName("孙悟空");setCRT(0.2);setCRTE(1.5);}}

3,继承自组件Hero,创建抽象装备类Equipment,定义装饰新功能的接口,以重写为新的功能供外部调用

package com.brave.decorator.pesticide.equipment;import com.brave.decorator.pesticide.hero.Hero;/*** 抽象装备*  -每个具体装备都继承自此类* * @author Brave**/
public abstract class Equipment extends Hero{// 强制重写-装备名称public abstract String getName();// 输出准备此件装备后的所有装备信息public abstract double getHP();public abstract double getMP();public abstract double getATK();public abstract double getDEF();public abstract double getCRT();public abstract double getCRTE();public abstract double getMS();public abstract double getAB();public abstract String getEquipment();// 强制重写-输出装备此件装备后的全部属性public abstract void printHeroAttr();}

4,通过继承Equipment类创建具体装备类
此类持有一个具体英雄(Hero)的引用,重写接口时对此引用信息做修改,以实现功能的变更和添加

创建6件装备:鞋子:100移速无尽之刃:50%暴击+50%暴击效果破甲弓:100攻击+100破甲冰痕之握:100防御+100魔法装饰泣血之刃:100攻击+100生命破军:200攻击

1)鞋子:增加100点移动速度

package com.brave.decorator.pesticide.equipment;import com.brave.decorator.pesticide.hero.Hero;/*** 鞋子:增加100点移动速度* @author Brave**/
public class Shoes extends Equipment {private Hero hero;public Shoes(Hero hero) {this.hero = hero;}@Overridepublic void printHeroAttr() {System.out.println("name = " + getName());System.out.println("生命值:HP = " + getHP());System.out.println("魔法值:MP = " + getMP());System.out.println("攻击力:ATK = " + getATK());System.out.println("防御力:DEF = " + getDEF());System.out.println("暴击率加成:CRT = " + getCRT());System.out.println("暴击效果:CRTE = " + getCRTE());System.out.println("移动速度加成:MS = " + getMS());System.out.println("破甲加成:AB = " + getAB());System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment());}@Overridepublic String getName() {return "鞋子";}@Overridepublic double getHP() {return hero.getHP();}@Overridepublic double getMP() {return hero.getMP();}@Overridepublic double getATK() {return hero.getATK();}@Overridepublic double getDEF() {return hero.getDEF();}@Overridepublic double getCRT() {return hero.getCRT();}@Overridepublic double getCRTE() {return hero.getCRTE();}@Overridepublic double getMS() {return hero.getMS() + 100;}@Overridepublic String getEquipment() {return hero.getEquipment() + getName() + ",";}@Overridepublic double getAB() {return hero.getAB();}}

2)无尽之刃:50%暴击+50%暴击效果

package com.brave.decorator.pesticide.equipment;import com.brave.decorator.pesticide.hero.Hero;/*** 无尽之刃:增加暴击率50%.暴击效果50%* @author Brave**/
public class InfinitySword extends Equipment {private Hero hero;public InfinitySword(Hero hero) {this.hero = hero;}@Overridepublic void printHeroAttr() {System.out.println("name = " + getName());System.out.println("生命值:HP = " + getHP());System.out.println("魔法值:MP = " + getMP());System.out.println("攻击力:ATK = " + getATK());System.out.println("防御力:DEF = " + getDEF());System.out.println("暴击率加成:CRT = " + getCRT());System.out.println("暴击效果:CRTE = " + getCRTE());System.out.println("移动速度加成:MS = " + getMS());System.out.println("破甲加成:AB = " + getAB());System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment());}@Overridepublic String getName() {return "无尽之刃";}@Overridepublic double getHP() {return hero.getHP();}@Overridepublic double getMP() {return hero.getMP();}@Overridepublic double getATK() {return hero.getATK();}@Overridepublic double getDEF() {return hero.getDEF();}@Overridepublic double getCRT() {return hero.getCRT() + 0.5;}@Overridepublic double getCRTE() {return hero.getCRTE() + 0.5;}@Overridepublic double getMS() {return hero.getMS();}@Overridepublic String getEquipment() {return hero.getEquipment() + getName() + ",";}@Overridepublic double getAB() {return hero.getAB();}}

3)破甲弓:100攻击+100破甲

package com.brave.decorator.pesticide.equipment;import com.brave.decorator.pesticide.hero.Hero;/*** 破甲弓:100攻击+100破甲* @author Brave**/
public class ArmorBow extends Equipment {private Hero hero;public ArmorBow(Hero hero) {this.hero = hero;}@Overridepublic void printHeroAttr() {System.out.println("name = " + getName());System.out.println("生命值:HP = " + getHP());System.out.println("魔法值:MP = " + getMP());System.out.println("攻击力:ATK = " + getATK());System.out.println("防御力:DEF = " + getDEF());System.out.println("暴击率加成:CRT = " + getCRT());System.out.println("暴击效果:CRTE = " + getCRTE());System.out.println("移动速度加成:MS = " + getMS());System.out.println("破甲加成:AB = " + getAB());System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment());}@Overridepublic String getName() {return "破甲弓";}@Overridepublic double getHP() {return hero.getHP();}@Overridepublic double getMP() {return hero.getMP();}@Overridepublic double getATK() {return hero.getATK() + 100;}@Overridepublic double getDEF() {return hero.getDEF();}@Overridepublic double getCRT() {return hero.getCRT();}@Overridepublic double getCRTE() {return hero.getCRTE();}@Overridepublic double getMS() {return hero.getMS();}@Overridepublic String getEquipment() {return hero.getEquipment() + getName() + ",";}@Overridepublic double getAB() {return hero.getAB() + 100;}}

4)冰痕之握:100防御+100魔法

package com.brave.decorator.pesticide.equipment;import com.brave.decorator.pesticide.hero.Hero;/*** 复活甲:100防御+100魔法值* @author Brave**/
public class IceMarkGrip extends Equipment {private Hero hero;public IceMarkGrip(Hero hero) {this.hero = hero;}@Overridepublic void printHeroAttr() {System.out.println("name = " + getName());System.out.println("生命值:HP = " + getHP());System.out.println("魔法值:MP = " + getMP());System.out.println("攻击力:ATK = " + getATK());System.out.println("防御力:DEF = " + getDEF());System.out.println("暴击率加成:CRT = " + getCRT());System.out.println("暴击效果:CRTE = " + getCRTE());System.out.println("移动速度加成:MS = " + getMS());System.out.println("破甲加成:AB = " + getAB());System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment());}@Overridepublic String getName() {return "冰痕之握";}@Overridepublic double getHP() {return hero.getHP();}@Overridepublic double getMP() {return hero.getMP() + 100;}@Overridepublic double getATK() {return hero.getATK();}@Overridepublic double getDEF() {return hero.getDEF() + 100;}@Overridepublic double getCRT() {return hero.getCRT();}@Overridepublic double getCRTE() {return hero.getCRTE();}@Overridepublic double getMS() {return hero.getMS();}@Overridepublic String getEquipment() {return hero.getEquipment() + getName() + ",";}@Overridepublic double getAB() {return hero.getAB();}}

5)泣血之刃:100攻击+100生命

package com.brave.decorator.pesticide.equipment;import com.brave.decorator.pesticide.hero.Hero;/*** 泣血之刃:100攻击+100生命值* @author Brave**/
public class BloodSword extends Equipment {private Hero hero;public BloodSword(Hero hero) {this.hero = hero;}@Overridepublic void printHeroAttr() {System.out.println("name = " + getName());System.out.println("生命值:HP = " + getHP());System.out.println("魔法值:MP = " + getMP());System.out.println("攻击力:ATK = " + getATK());System.out.println("防御力:DEF = " + getDEF());System.out.println("暴击率加成:CRT = " + getCRT());System.out.println("暴击效果:CRTE = " + getCRTE());System.out.println("移动速度加成:MS = " + getMS());System.out.println("破甲加成:AB = " + getAB());System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment());}@Overridepublic String getName() {return "泣血之刃";}@Overridepublic double getHP() {return hero.getHP() + 100;}@Overridepublic double getMP() {return hero.getMP();}@Overridepublic double getATK() {return hero.getATK() + 100;}@Overridepublic double getDEF() {return hero.getDEF();}@Overridepublic double getCRT() {return hero.getCRT();}@Overridepublic double getCRTE() {return hero.getCRTE();}@Overridepublic double getMS() {return hero.getMS();}@Overridepublic String getEquipment() {return hero.getEquipment() + getName() + ",";}@Overridepublic double getAB() {return hero.getAB();}}

6)破军:200攻击

package com.brave.decorator.pesticide.equipment;import com.brave.decorator.pesticide.hero.Hero;/*** 破军:200攻击* @author Brave**/
public class Breach extends Equipment {private Hero hero;public Breach(Hero hero) {this.hero = hero;}@Overridepublic void printHeroAttr() {System.out.println("name = " + getName());System.out.println("生命值:HP = " + getHP());System.out.println("魔法值:MP = " + getMP());System.out.println("攻击力:ATK = " + getATK());System.out.println("防御力:DEF = " + getDEF());System.out.println("暴击率加成:CRT = " + getCRT());System.out.println("暴击效果:CRTE = " + getCRTE());System.out.println("移动速度加成:MS = " + getMS());System.out.println("破甲加成:AB = " + getAB());System.out.println(getEquipment().equals("") ? "" : "装备:equipment = " + getEquipment());}@Overridepublic String getName() {return "破甲弓";}@Overridepublic double getHP() {return hero.getHP();}@Overridepublic double getMP() {return hero.getMP();}@Overridepublic double getATK() {return hero.getATK() + 200;}@Overridepublic double getDEF() {return hero.getDEF();}@Overridepublic double getCRT() {return hero.getCRT();}@Overridepublic double getCRTE() {return hero.getCRTE();}@Overridepublic double getMS() {return hero.getMS();}@Overridepublic String getEquipment() {return hero.getEquipment() + getName() + ",";}@Overridepublic double getAB() {return hero.getAB();}}

5,测试装饰模式,逐一为英雄装饰6件装备,打印日志查看装饰后的英雄属性

package com.brave.decorator.pesticide;import com.brave.decorator.pesticide.equipment.ArmorBow;
import com.brave.decorator.pesticide.equipment.BloodSword;
import com.brave.decorator.pesticide.equipment.Breach;
import com.brave.decorator.pesticide.equipment.IceMarkGrip;
import com.brave.decorator.pesticide.equipment.InfinitySword;
import com.brave.decorator.pesticide.equipment.Shoes;
import com.brave.decorator.pesticide.hero.Hero;
import com.brave.decorator.pesticide.hero.MonkeyKing;/*** 测试装饰模式* * 在不修改任何底层代码的情况下.为对象赋予新的职责* 装饰者模式:动态地将责任附加到对象上,若要拓展功能,装饰者提供了比继承更有弹性的替代方案* * @author Brave**/
public class Client {public static void main(String[] args) {System.out.println("*****************初始化英雄******************");Hero hero = new MonkeyKing();hero.printHeroAttr();System.out.println("*****************装饰鞋子:100移速******************");Hero shoes = new Shoes(hero);shoes.printHeroAttr();System.out.println("*****************装饰无尽之刃:50%暴击+50%暴击效果******************");Hero infinitySword = new InfinitySword(shoes);infinitySword.printHeroAttr();System.out.println("*****************装饰破甲弓:100攻击+100破甲******************");Hero armorBow = new ArmorBow(infinitySword);armorBow.printHeroAttr();System.out.println("*****************装饰冰痕之握:100防御+100魔法******************");Hero iceMarkGrip = new IceMarkGrip(armorBow);iceMarkGrip.printHeroAttr();System.out.println("*****************装饰泣血之刃:100攻击+100生命******************");Hero bloodSword = new BloodSword(iceMarkGrip);bloodSword.printHeroAttr();System.out.println("*****************装饰破军:200攻击******************");Hero breach = new Breach(bloodSword);breach.printHeroAttr();}}

6,打印日志输出,查看属性

*****************初始化英雄******************
name = 孙悟空
生命值:HP = 100.0
魔法值:MP = 100.0
攻击力:ATK = 100.0
防御力:DEF = 100.0
暴击率加成:CRT = 0.2
暴击效果:CRTE = 1.5
移动速度加成:MS = 0.0
*****************装饰鞋子:100移速******************
name = 鞋子
生命值:HP = 100.0
魔法值:MP = 100.0
攻击力:ATK = 100.0
防御力:DEF = 100.0
暴击率加成:CRT = 0.2
暴击效果:CRTE = 1.5
移动速度加成:MS = 100.0
破甲加成:AB = 0.0
装备:equipment = 鞋子,
*****************装饰无尽之刃:50%暴击+50%暴击效果******************
name = 无尽之刃
生命值:HP = 100.0
魔法值:MP = 100.0
攻击力:ATK = 100.0
防御力:DEF = 100.0
暴击率加成:CRT = 0.7
暴击效果:CRTE = 2.0
移动速度加成:MS = 100.0
破甲加成:AB = 0.0
装备:equipment = 鞋子,无尽之刃,
*****************装饰破甲弓:100攻击+100破甲******************
name = 破甲弓
生命值:HP = 100.0
魔法值:MP = 100.0
攻击力:ATK = 200.0
防御力:DEF = 100.0
暴击率加成:CRT = 0.7
暴击效果:CRTE = 2.0
移动速度加成:MS = 100.0
破甲加成:AB = 100.0
装备:equipment = 鞋子,无尽之刃,破甲弓,
*****************装饰冰痕之握:100防御+100魔法******************
name = 冰痕之握
生命值:HP = 100.0
魔法值:MP = 200.0
攻击力:ATK = 200.0
防御力:DEF = 200.0
暴击率加成:CRT = 0.7
暴击效果:CRTE = 2.0
移动速度加成:MS = 100.0
破甲加成:AB = 100.0
装备:equipment = 鞋子,无尽之刃,破甲弓,冰痕之握,
*****************装饰泣血之刃:100攻击+100生命******************
name = 泣血之刃
生命值:HP = 200.0
魔法值:MP = 200.0
攻击力:ATK = 300.0
防御力:DEF = 200.0
暴击率加成:CRT = 0.7
暴击效果:CRTE = 2.0
移动速度加成:MS = 100.0
破甲加成:AB = 100.0
装备:equipment = 鞋子,无尽之刃,破甲弓,冰痕之握,泣血之刃,
*****************装饰破军:200攻击******************
name = 破甲弓
生命值:HP = 200.0
魔法值:MP = 200.0
攻击力:ATK = 500.0
防御力:DEF = 200.0
暴击率加成:CRT = 0.7
暴击效果:CRTE = 2.0
移动速度加成:MS = 100.0
破甲加成:AB = 100.0
装备:equipment = 鞋子,无尽之刃,破甲弓,冰痕之握,泣血之刃,破甲弓,

四,装饰模式的优点与缺点

装饰模式的优点:
1,装饰模式与继承的目的都是扩展对象功能,但装饰模式比继承更加灵活性。装饰模式允许系统动态决定添加装饰,或移除装饰继承关系是静态的,在系统运行前决定
2,可以灵活的"改造"对象,使用不同装饰器或改变排列组合顺序,实现多种组合装饰模式的缺点:装饰模式使用组合实现新功能的添加,相比继承的实现使用了较少的类但由于装饰模式的特性,会产生比使用继承关系更多的对象而这些对象都很相似,数量也较多,所以加大了系统错误的排查难度

模式到这里就简单的说完了,先备注一些后面要加入的部分
java中使用的装饰模式-IO
装饰模式和其他模式的区别,例如和适配器

11,装饰模式-孙悟空的六神装相关推荐

  1. iOS 11开发教程(六)iOS11Main.storyboard文件编辑界面

    iOS 11开发教程(六)iOS11Main.storyboard文件编辑界面 在1.2.2小节中提到过编辑界面(Interface builder),编辑界面是用来设计用户界面的,单击打开Main. ...

  2. main 函数解析(二)—— Linux-0.11 学习笔记(六)

    main函数解析(二)--Linux-0.11 学习笔记(六) 4.6 blk_dev_init函数 void blk_dev_init(void) {int i;for (i=0 ; i<NR ...

  3. Linux0.11 execve函数(六)

    系列文章目录 Linux 0.11启动过程分析(一) Linux 0.11 fork 函数(二) Linux0.11 缺页处理(三) Linux0.11 根文件系统挂载(四) Linux0.11 文件 ...

  4. [机缘参悟-11]:“孙悟空”包含的佛学思想和人生哲理

    作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:[机缘参悟-11]:"孙悟空"包含的佛学思想和人生哲理_文火冰糖的硅基工坊的博 ...

  5. main() 函数解析(一)——Linux-0.11 剖析笔记(六)

    文章目录 1. 宏定义`_syscall0` 2. `setup.s`读取的参数 3. 读取CMOS实时时钟信息 3.1 `outb_p(value,port)` 3.2 `inb_p(port)` ...

  6. C++ 11 深度学习(六)智能指针综述

    以下三种智能指针均为类模板 1.shared_ptr  共享指针   ,多个指针指向同一个对象,最后一个指针被销毁时,这个对象会被释放. 2.week_ptr 是辅助shared_ptr工作的 3.u ...

  7. 六耳猕猴并不存在,真假猴王的六耳原来是他!

    <西游记>第五十八回"二心搅乱大乾坤,一体难修真寂灭",孙悟空.六耳猕猴引发的真假美猴王可谓是全书最精彩的部分之一,悟空与师父唐三藏观念上发生冲突,唐三藏一气之下将孙悟 ...

  8. “燕云十六将”之Lorna(14)

    上周写了<"燕云十六将"之张永生(13)>,这周写本系列中惟一没有在CSDN全职工作过,但对我帮助很大的朋友Lorna . 先说说我的性格吧! 07年底,有次我在公司的 ...

  9. “燕云十六将”之张永生(13)

    上周写了<"燕云十六将"之Jason郝钰(12)>,本周说的是新媒体市场部的张永生(部门名字有点长,可能我没写对). 2008年5月份,几位朋友给我过生日.在坐的都是人 ...

最新文章

  1. openSUSE 新的源(镜像)
  2. 高效使用Bitmaps(二) 后台加载Bitmap
  3. 深入Redis内部-Redis 源码讲解
  4. arcgis怎么运行python_在arcgis上用python脚本(arcpy)做数据批处理
  5. PyTorch基础(part7)--CNN
  6. 代码自解释不是不写注释的理由
  7. 上海事职业培训软件测试高级,《软件测试人员(Java)(4级)》人力资源和社会保障部教材办公室、中国就业培训技术指导中心上海分中心、上海市职业培训研究发展中心 编_孔网...
  8. android自动布局优先级,自动布局AutoLayout
  9. 《代码敲不队》第八次团队作业:Alpha冲刺 第五天
  10. JAVA:泛型通配符T,E,K,V区别,T以及Class,Class的区别
  11. JAVA如何选中一行上移_js操作table中tr的顺序实现上移下移一行的效果
  12. 【图像压缩】多层超先验模型 《Coarse-to-Fine Hyper-Prior Modeling for Learned Image Compression》
  13. python k线斜率计算公式_通达信公式K线斜率+选股指标源码
  14. nginx 504 Gateway Time-out错误解决办法
  15. 如何用大数据戳穿“空城计”
  16. 可以使用ActualHeight来判断textblock是否已经trimming
  17. 工作处境不好的时候,学会三思(三种思考)
  18. 淘宝 直通车 _h python源码
  19. 区块链供应链金融有着怎样的意义?
  20. 绝地大逃杀官方指定迅游加速

热门文章

  1. 五个实体店营销方案,彻底打开你的思维,再也不用担心顾客不进店
  2. FTP连接Linux时报cannot change directory错误的解决办法
  3. 打印图形——空心的倒三角形
  4. 实验一 交换下的冗余链路设计
  5. wifi Direct相关
  6. 技术人员和非技术人员如何写出优质博客?-涵子的个人想法
  7. Visual Tracking Dataset UCSB
  8. samba,让ubuntu与windows实现文件共享
  9. 孩子阅读好处多,如何让孩子爱上阅读?只要一个方法
  10. 【Linux】X11VNC安装指导