穿什么有这么重要?--装饰模式

1.1 穿什么有这么重要?

约会穿什么?
"那要看你想给人家什么印象?是比较年轻,还是比较干练;是比较颓废,还是要比较阳光;也有可能你想给人家一种极其难忘的印象,那穿法又大不一样了!"
"你这话怎么讲?"
"年轻,不妨走点Hip-Hop路线,大T恤、垮裤、球鞋,典型的年轻人装扮。"
"啊,这不是我喜欢的风格,我从来也没这样穿过。"
"那就换一种,所谓干练,就是要有外企高级白领的样,黑西装、黑领带、黑墨镜、黑皮鞋……"
"你这叫白领?我看是社会人。不行不行。"
"哈,来颓废的吧,颓废其实也是一种个性,可以吸引一些喜欢叛逆的女生。一般来说,其标志是:头发可养鸟、胡子能生虫、衬衣没纽扣、香烟加狐臭。"
"这根本就是'肮脏'的代表吗,开什么玩笑。你刚才提到给人家难忘印象,是什么样的穿法?"
"哈,这当然是绝妙的招了,如果你照我说的去做,娇娇想忘都难。"
"快说快说,是什么?"
"大红色披风下一身蓝色紧身衣,胸前一个大大的'S',表明你其实穿的是'小号',还有最重要的是,一定要'内裤外穿'……"
"喂,你拿我寻开心呀,那是'超人'的打扮呀,'S'代表的也不是'Small',是'Super'的意思。"哈,你终于明白了!我其实想表达的意思就是,你完全可以随便一些,平时穿什么,明天还是穿什么,男生嘛,只要干净一些就可以了,关键不在于你穿什么,而在于你人怎么样。对自己都这么没信心,如何追求女孩子?"

1.2 扮靓第一版

package code.chapter6.decorator1;public class Person {private String name;public Person(String name) {this.name = name;}public void wearTShirts() {System.out.print(" 大T恤");}public void wearBigTrouser() {System.out.print(" 垮裤");}public void wearSneakers() {System.out.print(" 球鞋");}public void wearSuit() {System.out.print(" 西装");}public void wearTie() {System.out.print(" 领带");}public void wearLeatherShoes() {System.out.print(" 皮鞋");}public void show() {System.out.println("装扮的"+name);}
}
package code.chapter6.decorator1;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		Person xc = new Person("小菜");System.out.println(" 第一种装扮:");xc.wearTShirts();xc.wearBigTrouser();xc.wearSneakers();xc.show();System.out.println(" 第二种装扮:");xc.wearSuit();xc.wearTie();xc.wearLeatherShoes();xc.show();System.out.println();System.out.println("**********************************************");}
}

现在需要增加超人的装扮。如果改Person类,就违背了开放-封闭原则了,应该把这些服饰都写成了子类就好了。

1.3 扮靓第二版

package code.chapter6.decorator2;public class Person {private String name;public Person(String name) {this.name = name;}public void show() {System.out.println("装扮的"+name);}
}
package code.chapter6.decorator2;public abstract class Finery {public abstract void show();}
package code.chapter6.decorator2;public class TShirts extends Finery {public void show(){System.out.print(" 大T恤");}}
package code.chapter6.decorator2;public class BigTrouser extends Finery {public void show(){System.out.print(" 垮裤");}}
package code.chapter6.decorator2;public class LeatherShoes extends Finery {public void show(){System.out.print(" 皮鞋");}}
package code.chapter6.decorator2;public class Sneakers extends Finery {public void show(){System.out.print(" 球鞋");}}
package code.chapter6.decorator2;public class Suit extends Finery {public void show(){System.out.print(" 西装");}}
package code.chapter6.decorator2;public class Tie extends Finery {public void show(){System.out.print(" 领带");}}
package code.chapter6.decorator2;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		Person xc = new Person("小菜");System.out.println(" 第一种装扮:");Finery dtx = new TShirts();Finery kk = new BigTrouser();Finery pqx = new Sneakers();dtx.show();kk.show();pqx.show();xc.show();System.out.println(" 第二种装扮:");Finery xz = new Suit();Finery ld = new Tie();Finery px = new LeatherShoes();xz.show();ld.show();px.show();xc.show();System.out.println();System.out.println("**********************************************");}
}

这样写就好比:你光着身子,当着大家的面,先穿T恤,再穿裤子,再穿鞋,仿佛在跳穿衣舞。难道你穿衣服都是在众目睽睽下穿的吗?"
"你的意思是,应该在内部组装完毕,然后再显示出来?这好像是建造者模式呀。"
"不是的,建造者模式要求建造的过程必须是稳定的,而现在我们这个例子,建造过程是不稳定的,比如完全可以内穿西装,外套T恤,再加披风,打上领带,皮鞋外再穿上破球鞋;当然也完全可以只穿条裤衩就算完成。换句话就是说,通过服饰组合出一个有个性的人完全可以有无数种方案,并非固定的。"
"啊,你说得对,其实先后顺序也是有讲究的,如你所说,先穿内裤后穿外裤,这叫凡人,内裤穿到外裤外面,那就是超人了。"
"哈,很会举一反三嘛,那你说该如何办呢?"
"我们需要把所需的功能按正确的顺序串联起来进行控制,这好像很难办哦。"
"不懂就学,其实也没什么稀罕的,这可以用一个非常有意思的设计模式来实现。"

1.4 装饰模式

装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

"啊,装饰这词真好,无论衣服、鞋子、领带、披风其实都可以理解为对人的装饰。"

"Component是定义一个对象接口,可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无须知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能[DPE]。"
"来看看基本的代码实现。"

package com.lhx.design.pattern.test;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		ConcreteComponent c = new ConcreteComponent();ConcreteDecoratorA d1 = new ConcreteDecoratorA();ConcreteDecoratorB d2 = new ConcreteDecoratorB();d1.SetComponent(c);	//首先用d1来包装cd2.SetComponent(d1);//再用有来包装d1d2.Operation();   	//最终执行d2的Operation()System.out.println();System.out.println("**********************************************");}
}//Component类
abstract class Component {public abstract void Operation();
}//ConcreteComponent类
class ConcreteComponent extends Component {public void Operation() {System.out.println("具体对象的实际操作");}}//Decorator类
abstract class Decorator extends Component {protected Component component;//装饰一个Component对象public void SetComponent(Component component) {this.component = component;}//重写Operation(),实际调用component的Operation方法public void Operation() {if (component != null) {component.Operation();}}
}//ConcreteDecoratorA类
class ConcreteDecoratorA extends Decorator {private String addedState;//本类独有子段,以区别于ConcreteDecoratorB类public void Operation() {super.Operation();//首先运行了原有Component的Operation()this.addedState = "具体装饰对象A的独有操作";//再执行本类独有功能System.out.println(this.addedState);}
}//ConcreteDecoratorB类
class ConcreteDecoratorB extends Decorator {public void Operation() {super.Operation();//首先运行了原有Component的Operation()this.AddedBehavior();//再执行本类独有功能}//本类独有方法,以区别于ConcreteDecoratorA类private void AddedBehavior() { System.out.println("具体装饰对象B的独有操作");}
}
package com.lhx.design.pattern.test;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		ConcreteComponent c = new ConcreteComponent();ConcreteDecoratorA d1 = new ConcreteDecoratorA();ConcreteDecoratorB d2 = new ConcreteDecoratorB();d1.SetComponent(c);	//首先用d1来包装cd2.SetComponent(d1);//再用有来包装d1d2.Operation();   	//最终执行d2的Operation()System.out.println();System.out.println("**********************************************");}
}//Component类
abstract class Component {public abstract void Operation();
}//ConcreteComponent类
class ConcreteComponent extends Component {public void Operation() {System.out.println("具体对象的实际操作");}}//Decorator类
abstract class Decorator extends Component {protected Component component;//装饰一个Component对象public void SetComponent(Component component) {this.component = component;}//重写Operation(),实际调用component的Operation方法public void Operation() {if (component != null) {component.Operation();}}
}//ConcreteDecoratorA类
class ConcreteDecoratorA extends Decorator {private String addedState;//本类独有子段,以区别于ConcreteDecoratorB类public void Operation() {super.Operation();//首先运行了原有Component的Operation()this.addedState = "具体装饰对象A的独有操作";//再执行本类独有功能System.out.println(this.addedState);}
}//ConcreteDecoratorB类
class ConcreteDecoratorB extends Decorator {public void Operation() {super.Operation();//首先运行了原有Component的Operation()this.AddedBehavior();//再执行本类独有功能}//本类独有方法,以区别于ConcreteDecoratorA类private void AddedBehavior() { System.out.println("具体装饰对象B的独有操作");}
}

我明白了,原来装饰模式是利用SetComponent来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中[DPE]。用刚才的例子来说就是,我们完全可以先穿外裤,再穿内裤,而不一定要先内后外。


"还有个问题,刚才写的那个例子中'人'类是Component还是ConcreteComponent呢?"
"哈,学习模式要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样道理,如果只有一ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。"
"啊,原来如此。在这里我们就没有必要有Component类了,直接让服饰类Decorator继承人类ConcreteComponent即可。"

1.5 扮靓第三版

package code.chapter6.decorator3;//人物形象接口
public interface ICharacter {public void show();}
package code.chapter6.decorator3;//服饰类
public class Finery implements ICharacter {protected ICharacter component;public void decorate(ICharacter component) {this.component=component;}public void show() {if (this.component != null){this.component.show();}}}

具体服饰类(ConcreteDecorator)

package code.chapter6.decorator3;public class TShirts extends Finery {public void show(){System.out.print(" 大T恤");super.show();}}
package code.chapter6.decorator3;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		Person xc = new Person("小菜");System.out.println(" 第一种装扮:");Sneakers pqx = new Sneakers();      //生成球鞋实例pqx.decorate(xc);                   //球鞋装饰小菜BigTrouser kk = new BigTrouser();   //生成垮裤实例kk.decorate(pqx);                   //垮裤装饰“有球鞋装饰的小菜”TShirts dtx = new TShirts();        //生成T恤实例dtx.decorate(kk);                   //T恤装饰“有垮裤球鞋装饰的小菜”dtx.show();                         //执行形象展示System.out.println(" 第二种装扮:");LeatherShoes px = new LeatherShoes();//生成皮鞋实例px.decorate(xc);                    //皮鞋装饰小菜Tie ld = new Tie();                 //生成领带实例ld.decorate(px);                    //领带装饰“有皮鞋装饰的小菜”Suit xz = new Suit();               //生成西装实例xz.decorate(ld);                    //西装装饰“有领带皮鞋装饰的小菜”xz.show();                          //执行形象展示System.out.println(" 第三种装扮:");Sneakers pqx2 = new Sneakers();     //生成球鞋实例pqx2.decorate(xc);                  //球鞋装饰小菜LeatherShoes px2 = new LeatherShoes();//生成皮鞋实例px2.decorate(pqx2);                 //皮鞋装饰“有球鞋装饰的小菜”BigTrouser kk2 = new BigTrouser();  //生成垮裤实例kk2.decorate(px2);                  //垮裤装饰“有皮鞋球鞋装饰的小菜”Tie ld2 = new Tie();                //生成领带实例ld2.decorate(kk2);                  //领带装饰“有垮裤皮鞋球鞋装饰的小菜”Strawhat cm2 = new Strawhat();      //生成草帽实例cm2.decorate(ld2);                  //草帽装饰“有领带垮裤皮鞋球鞋装饰的小菜”cm2.show();                         //执行形象展示System.out.println();System.out.println("**********************************************");}
}

如果我换一种装饰方式,比如说,增加草帽装扮,再重新组合一下服饰?

那就增加一个草帽子类,再修改一下装饰方案就好了。

package code.chapter6.decorator3;public class Strawhat extends Finery {public void show(){System.out.print(" 草帽");super.show();}}

1.6 商场收银程序再升级

先打8折,再满300返回100,算法可以是下面这样。

增加一个先折扣再返利的算法子类

package com.lhx.design.pattern.decoratorMode;public class CashReturnRebate extends CashSuper {private double moneyRebate = 1d;private double moneyCondition = 0d; //返利条件private double moneyReturn = 0d;    //返利值//先折扣,再返利。初始化时需要折扣参数,再输入返利条件和返利值。//比如“先8折,再满300返100”,就是moneyRebate=0.8,moneyCondition=300,moneyReturn=100public CashReturnRebate(double moneyRebate,double moneyCondition,double moneyReturn){this.moneyRebate = moneyRebate;this.moneyCondition = moneyCondition;this.moneyReturn = moneyReturn;}//先折扣,再返利public double acceptCash(double price,int num){double result = price * num * this.moneyRebate;if (moneyCondition>0 && result >= moneyCondition)result = result - Math.floor(result / moneyCondition) * moneyReturn; return result;}}
package com.lhx.design.pattern.decoratorMode;public class CashContext {private CashSuper cs;   //声明一个CashSuper对象//通过构造方法,传入具体的收费策略public CashContext(int cashType){switch(cashType){case 1:cs = new CashNormal();break;case 2:this.cs = new CashRebate(0.8d);break;case 3:this.cs = new CashRebate(0.7d);break;case 4:this.cs = new CashReturn(300d,100d);break;case 5:this.cs = new CashReturnRebate(0.8d,300d,100d);break;}}public double getResult(double price,int num){//根据收费策略的不同,获得计算结果return this.cs.acceptCash(price,num);}    
}

新类CashReturnRebate有原来的两个类:CashReturn和CashRebate有大量重复的代码,另外,如果我现在希望增加一个先满300返100,再打折扣的算法,你如何修改呢?再写一个新类吗?如果我们再增加购买送积分、购买抽奖、购买送小礼品等算法,并且有了各种各样的先后组合,你打算怎么处理呢?

1.7 简单工厂+策略+装饰模式实现

你这样是可以实现同样的功能,但与装饰模式比较起来,并不完美。仔细对比观察一下,还有什么东西没有?"

ConcreteComponent类不存在。那它应该是什么呢?

装饰模式有一个重要的优点,把类中的装饰功能从类中搬移去除,这样可以简化原有的类。我们现在的三个算法类,有没有最基础的呢?

CashSuper原来是抽象类,改成普通类,但实现ISale接口。

package com.lhx.design.pattern.decoratorMode.optimizeOne;public interface ISale {public double acceptCash(double price,int num);}

CashNormal,相当于ConcreteComponent,是最基本的功能实现,也就是单价×数量的原价算法。

package com.lhx.design.pattern.decoratorMode.optimizeOne;public class CashNormal implements ISale {//正常收费,原价返回public double acceptCash(double price,int num){return price * num; }    
}

另外两个CashSuper的子类算法,都在计算后,再增加一个super.acceptCash(result, 1)返回。

package com.lhx.design.pattern.decoratorMode.optimizeOne;public class CashRebate extends CashSuper {private double moneyRebate = 1d;//打折收费。初始化时必需输入折扣率。八折就输入0.8public CashRebate(double moneyRebate){this.moneyRebate = moneyRebate;}//计算收费时需要在原价基础上乘以折扣率public double acceptCash(double price,int num){double result = price * num * this.moneyRebate;return super.acceptCash(result,1);}}
package com.lhx.design.pattern.decoratorMode.optimizeOne;public class CashReturn extends CashSuper {private double moneyCondition = 0d; //返利条件private double moneyReturn = 0d;    //返利值//返利收费。初始化时需要输入返利条件和返利值。//比如“满300返100”,就是moneyCondition=300,moneyReturn=100public CashReturn(double moneyCondition,double moneyReturn){this.moneyCondition = moneyCondition;this.moneyReturn = moneyReturn;}//计算收费时,当达到返利条件,就原价减去返利值public double acceptCash(double price,int num){double result = price * num;if (moneyCondition>0 && result >= moneyCondition)result = result - Math.floor(result / moneyCondition) * moneyReturn; return super.acceptCash(result,1);   }}

重点在CashContext类,因为涉及组合算法,所以用装饰模式的方式进行包装,这里需要注意包装的顺序,先打折后满多少返多少,与先满多少返多少,再打折会得到完全不同的结果。

package com.lhx.design.pattern.decoratorMode.optimizeOne;public class CashContext {private ISale cs;   //声明一个ISale接口对象//通过构造方法,传入具体的收费策略public CashContext(int cashType){switch(cashType){case 1:this.cs = new CashNormal();break;case 2:this.cs = new CashRebate(0.8d);break;case 3:this.cs = new CashRebate(0.7d);break;case 4:this.cs = new CashReturn(300d,100d);break;case 5://先打8折,再满300返100CashNormal cn = new CashNormal();CashReturn cr1 = new CashReturn(300d,100d); CashRebate cr2 = new CashRebate(0.8d);cr1.decorate(cn);   //用满300返100算法包装基本的原价算法cr2.decorate(cr1);  //打8折算法装饰满300返100算法this.cs = cr2;      //将包装好的算法组合引用传递给cs对象break;case 6://先满200返50,再打7折CashNormal cn2 = new CashNormal();CashRebate cr3 = new CashRebate(0.7d);CashReturn cr4 = new CashReturn(200d,50d); cr3.decorate(cn2);  //用打7折算法包装基本的原价算法cr4.decorate(cr3);  //满200返50算法装饰打7折算法this.cs = cr4;      //将包装好的算法组合引用传递给cs对象break;}}public double getResult(double price,int num){//根据收费策略的不同,获得计算结果return this.cs.acceptCash(price,num);}    
}
package com.lhx.design.pattern.decoratorMode.optimizeOne;import java.util.Scanner;/*** 简单工厂+策略+装饰模式实现*/public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		int discount = 0; 		//商品折扣模式double price = 0d; 		//商品单价int num = 0;			//商品购买数量double totalPrices = 0d;//当前商品合计费用double total = 0d;		//总计所有商品费用Scanner sc = new Scanner(System.in);do {System.out.println("商品折扣模式如下:");	System.out.println("1.正常收费");	System.out.println("2.打八折");	System.out.println("3.打七折");	System.out.println("4.满300送100");	System.out.println("5.先打8折,再满300送100");	System.out.println("6.先满200送50,再打7折");	System.out.println("请输入商品折扣模式:");	discount = Integer.parseInt(sc.nextLine());System.out.println("请输入商品单价:");	price = Double.parseDouble(sc.nextLine());System.out.println("请输入商品数量:");	num = Integer.parseInt(sc.nextLine());System.out.println();	if (price>0 && num>0){//根据用户输入,将对应的策略对象作为参数传入CashContext对象中CashContext cc = new CashContext(discount);//通过Context的getResult方法的调用,可以得到收取费用的结果//让具体算法与客户进行了隔离totalPrices = cc.getResult(price,num);total = total + totalPrices;System.out.println();	System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	System.out.println();System.out.println("总计:"+ total+"元");	System.out.println();}}while(price>0 && num>0);System.out.println();System.out.println("**********************************************");}
}

客户端算法不变:

结果显示:

单位1000元,数量为1的商品,原需支付1000元,如果选择先8折再满300送100算法的话,就是1000×0.8=800元,满足两个300元,返200元,最终结果是客户只需支付600元。

单位500元,数量为4的商品,原需支付2000元,如果选择先满200送50再7折算法的话,就是2000中有10个200,送10×50=500元,所以2000-500=1500元,再打7折,1500×0.7,最终结果是客户只需支付1050元。

现在无论如何组合算法,哪怕是先打折再返现,再打折再返现,我都只需要更改CashContext类就可以了。目前代码确实做到了开放封闭。设计模式真是好!

1.8 装饰模式总结

"我觉得装饰模式是为已有功能动态地添加更多功能的一种方式。但到底什么时候用它呢?"
"答得很好,问的问题更加好。你起初的设计中,当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为,比如用西装或嘻哈服来装饰小菜,但这种做法的问题在于,它们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,就像你起初的那个'人'类,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了[DP]。所以就出现了上面那个例子的情况,我可以通过装饰,让你全副武装到牙齿,也可以让你只挂一丝到内裤。"
"就像你所说的,装饰模式的优点是,把类中的装饰功能从类中搬移去除,这样可以简化原有的类。像前面的原价算法就是最基础的类,而打折或返现,都算是装饰算法了。"
"是的,这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。我们不必去重复编写类似打折后再返现,或返现后再打折的代码,对于装饰模式来说,只是多几种组合而已。"
"这个模式真不错,我以后要记着常使用它。"
"你可要当心哦,装饰模式的装饰顺序很重要哦,比如加密数据和过滤词汇都可以是数据持久化前的装饰功能,但若先加密了数据再用过滤功能就会出问题了,最理想的情况,是保证装饰类之间彼此独立,这样它们就可以以任意的顺序进行组合了。"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/587389.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3_2024_7天【回顾上篇watch常见的后两种场景】完

随笔:这年头工作不好找咯,大家有学历提升的赶快了,还有外出人多注意身体,没错我在深圳这边阳了,真的绝啊,最尴尬的还给朋友传染了!!! 之前三种的监听情况,监听…

【高校科研动态】贵州师大博士生封清为一作在J. Clean. Prod.发文:中国扶贫搬迁对生态影响的量化研究——以贵州省为例

目录 1.文章简介 2.主要研究内容 3.文章引用 1.文章简介 论文名称:Quantifying the extent of ecological impact from Chinas poverty alleviation relocation program: A case study in Guizhou Province 第一作者及通讯作者:封清&#…

一文教你如何使用sngrep跟踪分析sip信令

sngrep是一个用于分析SIP信令的工具,它可以捕获和解码SIP信令也是一款专业的sip抓包工具,且可以解析tcpdump抓出来的包。 sip协议(会话初始协议),是一种多媒体通信协议; sip协议的消息主体(报文…

联系媒体要有方法莫让投稿发文章只剩一声长叹相见恨晚

曾有一位饱经世事的前辈以一句至理名言警醒世人:“人之所以领悟道理,往往不是源于抽象的道理本身,而是生活给予的实实在在的挫折教训,如同撞南墙一般的痛彻觉醒;同样,让人豁然开朗的,也不是空洞的说教,而是实实在在的人生磨砺。”这一哲理,放在我们日常工作中亦有深刻的启示作用…

ISELED氛围灯方案简介

ISELED目录 一、ISELED 介绍二、ISELED联盟三、ISELED的应用方向四、NXP在ISELED上的贡献一、ISELED 介绍 在当今汽车行业疯狂内卷的时代,各车企把更多精力花费在了车辆内部座舱的设计上,氛围灯出现其实已经有好多年,从最开始的单色氛围灯,到64色、128氛围灯,再到现在的2…

Linux系统----------探索mysql数据库MHA高可用

目录 一、MHA概述 1.1 什么是 MHA 1.2MHA 的组成 1.2.1MHA Node(数据节点) 1.2.2MHA Manager(管理节点) 1.3MHA 的特点 1.4MHA工作原理 1.5数据同步的方式 1.5.1同步复制 1.5.2异步复制 1.5.3半同步复制 二、搭建 MySQ…

CTK插件框架学习-信号槽(05)

CTK插件框架学习-事件监听(04)https://mp.csdn.net/mp_blog/creation/editor/137171155 一、主要流程 信号发送者告诉服务要发送的信号信号发送者发送信号信号接收者告诉服务当触发某个订阅的主题时通知槽函数信号接收者处理槽函数信号槽参数类型必须为(const ctk…

redis数据类型介绍

字符串string: 字符串类型是Redis中最为基础的数据存储类型,是一个由字节组成的序列,他在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据,如JPEG图像数据货Json对象描述信息等,是标准的key…

蓝桥杯嵌入式学习笔记(7):ADC程序设计

目录 前言 1. ADC原理 1.1 主要特性 1.2 模拟输出电路图 2. 使用CubeMX进行源工程的配置 2.1 引脚配置 2.2 配置AD1 2.3 配置AD2 2.4 配置时钟 3. 代码编程 3.1 预备工作 3.2 bsp_adc.h文件编写 3.3 bsp_adc.c文件编写 3.4 main.c编写 3.4.1 时钟函数配置 3…

windows下通过vscode访问ubuntu(绝大部分Linux下开发所采用的方案)

前言 本篇博客是介绍VSCode远程连接Ubuntu进行开发的解决方案,前提是安装好了VMWare,Ubuntu,windows下的VSCode。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关…

黄金票据攻击

黄金票据攻击——域内横向移动技术 一、黄金票据攻击介绍: 黄金票据攻击是一种滥用Kerberos身份认证协议的攻击方式,它允许攻击者伪造域控krbtgt用户的TGT(Ticket-Granting Ticket)。通过这种方法,攻击者可以生成有效…

vue2项目安装(使用vue-cli脚手架)

使用npm安装 安装镜像(使npm创建项目更快):镜像可更换 npm config set registry https://registry.npmmirror.com1.全局安装vue-cli(一次) npm install -g vue/cli 2. 查看vue-cli 版本 vue --version 3. 创建项目…