设计模式应用之java代码实现(一)

文章目录

  • 前言
  • 外观模式
  • 享元模式
  • 职责链模式
  • 命令模式
  • 命令模式2
  • 命令模式3+备忘录模式
  • 迭代器模式
  • 观察者模式
  • 状态模式

前言

本篇博客截取的是**《C#设计模式(第2版)》这本书课后习题里面的各个设计模式的典型习题并完成java代码实现,每个代码实现都有相应的业务需求背景可以帮助更好的理解设计模式,其中包括的设计模式包括外观模式、享元模式、职责链模式、命令模式、备忘录模式、迭代器模式、观察者模式以及状态模式**。后续会继续出其他设计模式的续集并就一些应用广泛的设计模式进行深入剖析。

外观模式

T1. P188 T5 外观模式
在计算机主机(Mainframe)中,只需按下主机的开机按钮(On()),即可调用其他硬件设备和软件的启动方法,如内存(Memory)的自检(Check())、CPU的运行(Run())、硬盘(HardDisk)的读取(Read())、操作系统(OS)的载入(Load())等,如果某一过程发生错误则计算机启动失败。试使用外观模式模拟该过程。


//外观角色Mainframe
class Mainframe{//维持对其他对象的引用private Memory memory;private CPU cpu;private HardDisk hardDisk;private OS os;public Mainframe(){memory=new Memory();cpu=new CPU();hardDisk=new HardDisk();os=new OS();}//调用其他对象的业务方法public void on(){memory.check();cpu.run();hardDisk.read();os.load();}
}
//子系统角色Memory
class Memory{void check(){System.out.println("内存启动自检...");}
}
//子系统角色CPU
class CPU{void run(){System.out.println("CPU启动运行...");}
}
//子系统角色HardDisk
class HardDisk{void read(){System.out.println("硬盘启动读取...");}
}
//子系统角色OS
class OS{void load(){System.out.println("操作系统启动载入...");}
}
//测试
public class MainframeTest {public static void main(String[] args) {//针对抽象外观编程Mainframe mainframe=new Mainframe();mainframe.on();}
}

享元模式

T2. P204 T5 享元模式
在屏幕中显示一个文本文档,其中相同的字符串“CSharp”共享同一个对象,而这些字符串的颜色和大小可以不同。现使用享元模式设计一个方案实现字符串对象的共享,要求绘制类图并使用编程实现。

//Color类充当外部状态类
class Color{private String color;public Color(String color) {this.color = color;}public void setColor(String color){this.color=color;}public String getColor(){return this.color;}
}
//Size充当外部状态类
class Size{private int value;public Size(int value){this.value=value;}public void setValue(int value){this.value=value;}public int getValue(){return this.value;}
}
//抽象共享字符串,担任抽象享元角色
abstract class AbstractSharedString{String content;public abstract String GetContent();public abstract void Display(Color color,Size size);
}
//共享字符串CSharp,担任具体享元角色
class SharedString extends AbstractSharedString{public SharedString(String content){this.content=content;}public String GetContent(){return content;}public void Display(Color color,Size size){System.out.println("内容: "+GetContent()+",颜色:"+color.getColor()+",大小:"+size.getValue());}
}
//SharedStringFactory充当享元工厂角色
class SharedStringFactory{private Map <String,Object>mp;public SharedStringFactory(){mp=new HashMap<>();}public AbstractSharedString getSharedString(String arg){if (!mp.containsKey(arg)) {AbstractSharedString str = new SharedString(arg);mp.put(arg, str);}return (AbstractSharedString)mp.get(arg);}
}
//客户类中测试显示两个颜色和大小不同的字符串”CSharp“
public class SharedStringTest {public static void main(String[] args) {AbstractSharedString str1,str2;SharedStringFactory factory=new SharedStringFactory();//红色5号字体str1=factory.getSharedString("CSharp");str1.Display(new Color("红色"),new Size(5));//黑色10号字体str2=factory.getSharedString("CSharp");str2.Display(new Color("黑色"),new Size(10));System.out.println(str1==str2);//输出true}
}

职责链模式

T3. P234 T4 职责链模式
客户类模拟情报人员,首先向级别最低的班长递交任务书,即军情,如果超出
班长的权力范围,则传递给排长,排长如果也不能处理则传递给营长,如果营长也不能处理则需要开会讨论。

//Mission充当请求角色
class Mission{String code;int enemyNumber;public Mission(String code, int enemyNumber) {this.code = code;this.enemyNumber = enemyNumber;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public int getEnemyNumber() {return enemyNumber;}public void setEnemyNumber(int enemyNumber) {this.enemyNumber = enemyNumber;}
}
//Officer充当抽象传递者角色
abstract class Officer{protected String name;protected Officer successor;public Officer(String name){this.name=name;}public void setSuccessor(Officer successor){this.successor=successor;}public abstract void handleRequest(Mission request);
}
//班长monitor充当具体传递者角色
class Monitor extends Officer{public Monitor(String name){super(name);}public void handleRequest(Mission request){if(request.getEnemyNumber()<10){System.out.println("班长" + name + "下达代号为" + request.getCode() + "的作 战任务,敌人数量为" + request.getEnemyNumber());}else{if(this.successor!=null){this.successor.handleRequest(request);}}}
}
//排长Platoon充当具体传递者角色
class Platoon extends Officer{public Platoon(String name){super(name);}public void handleRequest(Mission request){if(request.getEnemyNumber()>=10&&request.getEnemyNumber()<50){System.out.println("排长" + name + "下达代号为" + request.getCode() + "的作战任务,敌人数量为" + request.getEnemyNumber());}else{if(this.successor!=null){this.successor.handleRequest(request);}}}
}
//营长BattalionCommander充当具体传递者角色
class BattalionCommander extends Officer{public BattalionCommander(String name){super(name);}public void handleRequest(Mission request){if(request.getEnemyNumber()<200){System.out.println("营长" + name + "下达代号为" + request.getCode() + "的作战任务,敌人数量为" + request.getEnemyNumber());}else{System.out.println("敌人数量过多,共有人数:"+request.getEnemyNumber()+",所以需要共同讨论代号为"+request.getCode()+"的作战任务");}}
}
public class MissionTest {public static void main(String[] args) {Officer officer1,officer2,officer3;//班长张三officer1=new Monitor("张三");//排长李四officer2=new Platoon("李四");//营长王五officer3=new BattalionCommander("王五");//创建职责链officer1.setSuccessor(officer2);officer2.setSuccessor(officer3);//作战四个不同代号不同敌人数量的任务Mission mission1,mission2,mission3,mission4;mission1=new Mission("001",5);mission2=new Mission("010",20);mission3=new Mission("100",100);mission4=new Mission("101",500);//发送请求,请求对象通常为自定义类型officer1.handleRequest(mission1);officer1.handleRequest(mission2);officer1.handleRequest(mission3);officer1.handleRequest(mission4);}
}

命令模式

T4. P252 T3 命令模式
房间中的开关就是命令模式的一种实现,试使用命令模式来模拟开关的功能,可控制对象包括电灯和电风扇

//Command充当抽象命令类
abstract class Command{public abstract void executeOn();public abstract void executeOff();
}
//switch充当调用者(发送者)角色
class Switch{//维持一个抽象命令对象的引用private Command command;public Command getCommand() {return command;}public void setCommand(Command command) {this.command = command;}//发送请求的方法public void Click(){command.executeOn();command.executeOff();}
}
//LampCommand充当具体命令角色
class LampCommand extends Command{//维持对请求接收者的引用private Lamp lamp;public LampCommand(){lamp=new Lamp();}@Overridepublic void executeOn() {lamp.lighten();}@Overridepublic void executeOff() {lamp.quench();}
}
//FanCommand充当具体命令类
class FanCommand extends Command{//维持对请求接收者的引用private Fan fan;public FanCommand(){fan=new Fan();}@Overridepublic void executeOn() {fan.run();}@Overridepublic void executeOff() {fan.stop();}
}
//fan充当接受者命令
class Fan{public void run(){System.out.println("开电风扇");}public void stop(){System.out.println("关电风扇");}
}//Lamp充当接收者角色
class Lamp{public void lighten(){System.out.println("开电灯");}public void quench(){System.out.println("关电灯");}
}
public class SwitchTest {public static void main(String[] args) {Switch sw=new Switch();//定义命令对象Command commandLamp,commandFan;commandLamp=new LampCommand();commandFan=new FanCommand();//将电灯命令对象注入开关sw.setCommand(commandLamp);sw.Click();//将电风扇命令对象注入开关sw.setCommand(commandFan);sw.Click();}
}

命令模式2

  1. P252 T5(按题目要求完成)(命令模式)
    设计并实现一个简单的请求日志记录程序,将一组命令对象通过序列化写到
    日志文件中,并通过日志文件实现批处理操作
import java.io.*;
import java.util.ArrayList;//配置文件设置窗口类,充当请求发送者
class ConfigSettingWindow {//定义一个集合来存储每一次操作时的命令对象private ArrayList<Command> commands = new ArrayList<Command>();private Command command;//注入具体命令对象public void setCommand(Command command) {this.command = command;}//执行配置文件修改命令,同时将命令对象添加到命令集合中public void call(String args) {command.execute(args);commands.add(command);}//记录请求日志,生成日志文件,将命令集合写入日志文件public void save() {FileUtil.writeCommands(commands);}//从日志文件中提取命令集合,并循环调用每一个命令对象的execute()方法来实现配置文件的重新设置public void recover() {ArrayList list;list = FileUtil.readCommands();for (Object obj : list) {((Command)obj).execute();}}
}//抽象命令类,由于需要将命令对象写入文件,因此它实现了Serializable接口
abstract class Command implements Serializable {//维持对接收者对象的引用protected ConfigOperator configOperator;protected String name; //命令名称protected String args; //命令参数public Command(String name) {this.name = name;}public String getName() {return this.name;}public void setName(String name) {this.name = name;}public void setConfigOperator(ConfigOperator configOperator) {this.configOperator = configOperator;}//声明两个抽象的执行方法execute()public abstract void execute(String args);public abstract void execute();
}//增加命令类:具体命令类
class InsertCommand extends Command {public InsertCommand(String name) {super(name);}public void execute(String args) {this.args = args;configOperator.insert(args);}public void execute() {configOperator.insert(this.args);}
}//修改命令类:具体命令类
class ModifyCommand extends Command {public ModifyCommand(String name) {super(name);}public void execute(String args) {this.args = args;configOperator.modify(args);}public void execute() {configOperator.modify(this.args);}
}
//删除命令类:具体命令类
class DeleteCommand extends Command {public DeleteCommand(String name) {super(name);}public void execute(String args) {this.args = args;configOperator.delete(args);}public void execute() {configOperator.delete(this.args);}
}//配置文件操作类:请求接收者。由于ConfigOperator类的对象是Command的成员对象,它也将随Command对象一起写入文件,因此ConfigOperator也需要实现Serializable接口
class ConfigOperator implements Serializable {public void insert(String args) {System.out.println("增加新节点:" + args);}public void modify(String args) {System.out.println("修改节点:" + args);}public void delete(String args) {System.out.println("删除节点:" + args);}
}//工具类:文件操作类
class FileUtil {//将命令集合写入日志文件public static void writeCommands(ArrayList commands) {try {FileOutputStream file = new FileOutputStream("config.log");//创建对象输出流用于将对象写入到文件中ObjectOutputStream objout = new ObjectOutputStream(new BufferedOutputStream(file));//将对象写入文件objout.writeObject(commands);objout.close();} catch (Exception e) {System.out.println("命令保存失败!");e.printStackTrace();}}//从日志文件中提取命令集合public static ArrayList readCommands() {try {FileInputStream file = new FileInputStream("config.log");//创建对象输入流用于从文件中读取对象ObjectInputStream objin = new ObjectInputStream(new BufferedInputStream(file));//将文件中的对象读出并转换为ArrayList类型ArrayList commands = (ArrayList) objin.readObject();objin.close();return commands;} catch (Exception e) {System.out.println("命令读取失败!");e.printStackTrace();return null;}}
}
public class RequestLogClientTest {public static void main(String[] args) {ConfigSettingWindow csw = new ConfigSettingWindow(); //定义请求发送者Command command; //定义命令对象ConfigOperator co = new ConfigOperator(); //定义请求接收者//四次对配置文件的更改command = new InsertCommand("增加");command.setConfigOperator(co);csw.setCommand(command);csw.call("网站首页");command = new InsertCommand("增加");command.setConfigOperator(co);csw.setCommand(command);csw.call("端口号");command = new ModifyCommand("修改");command.setConfigOperator(co);csw.setCommand(command);csw.call("网站首页");command = new ModifyCommand("修改");command.setConfigOperator(co);csw.setCommand(command);csw.call("端口号");System.out.println("----------------------------");System.out.println("保存配置");csw.save();System.out.println("----------------------------");System.out.println("恢复配置");System.out.println("----------------------------");csw.recover();}
}

命令模式3+备忘录模式

  1. P252 T5(在命令模式的基础上加上备忘录模式memento实现撤销操作)
    设计并实现一个简单的请求日志记录程序,将一组命令对象通过序列化写到
    日志文件中,并通过日志文件实现批处理操作

import java.util.List;public class RequestLogMementoTest {public static void main(String[] args) {CareTaker careTaker = new CareTaker();LogFile logFile = new LogFile();Command command = new RecordCommand(logFile);OS os = new OS(command);for (int i = 0; i < 10; i++) {os.call("记录下了第" + (i + 1) + "条日志");careTaker.addLogMemento(logFile.createMemento());System.out.println(logFile.getLogs());}LogMemento logMementos = careTaker.getLogMementos(5);logFile.restoreMemento(logMementos);System.out.println(logFile.getLogs());}
}
//请求发送者
class OS {//维持对一个抽象命令对象的引用private Command command;public OS(Command command) {this.command = command;}public Command getCommand() {return command;}public void setCommand(Command command) {this.command = command;}public void call(String log) {command.execute(log);}
}
//充当抽象命令类
abstract class Command {public abstract void execute(String log);
}
//充当具体命令类
class RecordCommand extends Command {//维持对请求接收者的引用private LogFile logFile;public RecordCommand(LogFile logFile) {this.logFile = logFile;}//命令执行方法,将调用请求接收者的业务方法@Overridepublic void execute(String log) {logFile.record(log);}
}//请求接收者,同时充当备忘录模式中的原发器
class LogFile {private List<String> logs = new ArrayList<>();public List<String> getLogs() {return logs;}public LogMemento createMemento() {LogFile logFile=new LogFile();List<String> l=new ArrayList<>();l.addAll(logs);logFile.setLogs(l);return new LogMemento(logFile);}public void restoreMemento(LogMemento memento) {this.logs = memento.getLogs();}public void setLogs(List<String> logs) {this.logs = logs;}public void record(String log) {logs.add(log);}
}//充当备忘录
class LogMemento {private List<String> logs;public LogMemento(LogFile logFile) {logs = logFile.getLogs();}public List<String> getLogs() {return logs;}public void setLogs(List<String> logs) {this.logs = logs;}@Overridepublic String toString() {return "LogMemento{" +"logs=" + logs +'}';}
}//负责人 保存备忘录
class CareTaker {private List<LogMemento> logMementos = new ArrayList<>();public LogMemento getLogMementos(int i) {return logMementos.get(i);}public void addLogMemento(LogMemento logMemento) {logMementos.add(logMemento);}
}

迭代器模式

T7. P284 T4
电视机遥控器是一个迭代器的现实应用,通过它可以实现对电视频道集合的遍历,
可以将电视机看成一个存储频道的聚合对象,试模拟电视机遥控器的实现。


import java.util.ArrayList;
import java.util.List;
//抽象聚合类
abstract class AbstractTelevisionList{//频道列表protected List<Object>objects=new ArrayList<Object>();public AbstractTelevisionList(List<Object>objects){this.objects=objects;}public void addObject(Object obj){this.objects.add(obj);}public void removeObject(Object obj){this.objects.remove(obj);}public List<Object> getObjects(){return this.objects;}//声明创建迭代器对象的抽象工厂方法public abstract AbstractIterator CreateIterator();
}
//具体聚合类,电视机作为存放频道的聚合对象
class TelevisionList extends AbstractTelevisionList{public TelevisionList(List<Object>Televisions){super(Televisions);}//实现创建迭代器对象的具体工厂方法@Overridepublic AbstractIterator CreateIterator() {return new RemoteControlIterator(this);}
};//抽象遥控器,充当抽象迭代器
interface AbstractIterator{void next();        //移至下一个元素boolean isLast();   //判断是否为最后一个元素void previous();  //移至上一个元素boolean isFirst();  //判断是否是第一个元素Object getNextItem();  //获取下一个元素Object getPreviousItem();  //获取上一个元素}
//电视遥控器,充当具体迭代器
class RemoteControlIterator implements AbstractIterator{private TelevisionList televisionList;private List<Object> products;private int cursor1;  //定义一个游标,用于记录正向遍历的位置;private int cursor2;  //定义一个游标,用于记录逆向遍历的位置;public RemoteControlIterator(TelevisionList list){this.televisionList=list;this.products=list.getObjects();//获取集合对象cursor1=0;  //设置正向遍历游标的初始值cursor2=products.size()-1;  //设置逆向遍历游标的初始值}@Overridepublic void next() {if(cursor1<products.size()){cursor1++;}}@Overridepublic boolean isLast() {return (cursor1==products.size());}@Overridepublic void previous() {if(cursor2>-1){cursor2--;}}@Overridepublic boolean isFirst() {return (cursor2==-1);}@Overridepublic Object getNextItem() {return products.get(cursor1);}@Overridepublic Object getPreviousItem(){return products.get(cursor2);}
}public class TelevisionRemoteControl {public static void main(String[] args) {List<Object> products=new ArrayList<>();products.add("中央电视台");products.add("浙江卫视");products.add("湖南卫视");products.add("江苏卫视");products.add("东方卫视");products.add("凤凰卫视");AbstractTelevisionList list;AbstractIterator iterator;list=new TelevisionList(products);  //创建聚合对象iterator=list.CreateIterator();  //创建迭代器对象System.out.println("正向遍历:");while(!iterator.isLast()){System.out.println(iterator.getNextItem()+",");iterator.next();}System.out.println("----------------------------");System.out.println("逆向遍历:");while(!iterator.isFirst()){System.out.println(iterator.getPreviousItem()+",");iterator.previous();}}
}

观察者模式

T8.P332 T6
某实时在线股票软件需要提供以下功能:
当股票购买者所购买的某支股票价格变化幅度达到5%时,系统将自动发送通知(包括新价格)给购买该股票的所有股民。试使用观察者模式设计并实现该系统。

//Investor充当抽象观察者
abstract class Investor{public abstract void response(Stock stock);
}
//ConcreteInvestor充当具体观察者
class ConcreteInvestor extends Investor{private String name;public ConcreteInvestor(String name){this.name=name;}public void response(Stock stock){System.out.print("提醒股民:"+name);System.out.print("----股票:"+stock.getStockName());System.out.print("价格波动幅度超过5%-------");System.out.println("新价格是:"+stock.getPrice()+".");}
}
//Stack充当抽象目标类
abstract class Stock{protected ArrayList<Investor> investors;protected String stockName;protected double price;//买股票public abstract void attach(Investor investor);//退股票public abstract void detach(Investor investor);public String getStockName() {return stockName;}public void setStockName(String stockName) {this.stockName = stockName;}public double getPrice() {return price;}public abstract void setPrice(double price);public abstract void notifyObserver();
}//ConcreteStock充当具体目标类
class ConcreteStock extends Stock{public ConcreteStock(String stockName,double price) {this.stockName=stockName;this.price=price;investors=new ArrayList<Investor>();}//买股票@Overridepublic void attach(Investor investor){investors.add(investor);}//退股票@Overridepublic void detach(Investor investor){investors.remove(investor);}//股票价格变化幅度达到5%时,自动通知所有购买该股票的股民@Overridepublic void setPrice(double price) {double range=Math.abs(price-this.price)/this.price;this.price=price;if(range>=0.05){this.notifyObserver();}}//遍历观察者集合,调用每一个股票购买者得response()方法@Overridepublic void notifyObserver() {for(Object obj:investors){((Investor)obj).response(this);}}
}public class StockTest {public static void main(String[] args) {//股民Investor investor1,investor2,investor3;investor1=new ConcreteInvestor("张三");investor2=new ConcreteInvestor("李四");investor3=new ConcreteInvestor("王五");Stock stock1=new ConcreteStock("中芯国际",100.00);stock1.attach(investor1);stock1.attach(investor2);stock1.attach(investor3);stock1.setPrice(105.00);}
}

状态模式

T9. P353 T4
传输门是传输系统中的重要装置。传输门具有Open(打开)、Closed(关闭)、Opening(正在打开)、StayOpen(保持打开)、Closing(正在关闭)5种状态。触发状态的转换事件有click、complete和timeout3种。事件与其相应的状态转换如图所示。试使用状态模式对传输门进行状态模拟,

//door充当环境类
class Door {public final DoorState CLOSED = new DoorClosed(this);public final DoorState OPENING = new DoorOpening(this);public final DoorState OPEN = new DoorOpen(this);public final DoorState CLOSING = new DoorClosing(this);public final DoorState STAYOPEN = new DoorStayOpen(this);private DoorState state = CLOSED;//设置传输门当前状态public void setState(DoorState state){this.state = state;}//根据当前状态输出对应的状态字符串public void getState(){System.out.println(state.getClass().getName());}//发生 click 事件时进行状态转换public void click() {state.click();}//发生 timeout 事件时进行状态转换public void timeout() {state.timeout();}//发生 complete 事件时进行状态转换public void complete() {state.complete();}
}
//定义所有状态类的基类DoorState,DoorState充当抽象状态类角色
abstract class DoorState {protected Door door ;public DoorState(Door door) {this.door = door;}public abstract void click();public abstract void complete();public abstract void timeout();
}
//DoorClosed充当具体状态类角色
class DoorClosed extends DoorState{public DoorClosed(Door door) {super(door);}public void click(){door.setState(door.OPENING);}@Overridepublic void complete() {door.setState(door.CLOSING);}@Overridepublic void timeout() {}
}
//DoorOpening充当具体状态类角色
class DoorOpening extends DoorState{public DoorOpening(Door door) {super(door);}@Overridepublic void click() {door.setState(door.CLOSING);}@Overridepublic void complete() {door.setState(door.OPEN);}@Overridepublic void timeout() {}
}//DoorOpen充当具体状态类角色
class DoorOpen extends DoorState{public DoorOpen(Door door) {super(door);}@Overridepublic void click() {door.setState(door.STAYOPEN);}@Overridepublic void complete() {}@Overridepublic void timeout() {door.setState(door.CLOSING);}
}//DoorClosing充当具体状态类角色
class DoorClosing extends DoorState{public DoorClosing(Door door) {super(door);}@Overridepublic void click() {door.setState(door.OPENING);}@Overridepublic void complete() {door.setState(door.CLOSED);}@Overridepublic void timeout() {}
}
//DoorStayOpen充当具体状态类角色
class DoorStayOpen extends DoorState{public DoorStayOpen(Door door) {super(door);}@Overridepublic void click() {door.setState(door.CLOSING);}@Overridepublic void complete() {}@Overridepublic void timeout() {}
}
public class TransmissionDoor {public static void main(String[] args) {Door aDoor = new Door();aDoor.getState();aDoor.click();aDoor.getState();aDoor.complete();aDoor.getState();aDoor.timeout();aDoor.getState();}
}

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

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

相关文章

【链接MySQL】教你用VBA链接MySQL数据库

hi&#xff0c;大家好呀&#xff01; 之前呢&#xff0c;给大家分享过一个自制链接表管理器的文章&#xff0c;文章中有链接SQL Server数据库的代码&#xff0c;大家对这一段代码比较有兴趣&#xff0c;既然大家有兴趣&#xff0c;那我们今天就来讲一下链接数据库的代码。 这…

nginx配置全解析

#用于指定 Nginx 进程运行的用户和用户组&#xff0c;root 用户具有系统的最高权限&#xff08;潜在的安全漏洞&#xff09;可以用use nginx>非特权用户&#xff08;通常是 nginx&#xff09;的身份运行 user root; #Nginx服务器能够同时处理的连接数量(设置服务器cpu核数)…

抽象工厂模式-C语言实现

说明&#xff1a; 均由 chatgpt生成&#xff0c;实例可以看出无法运行&#xff0c;仅供参考~ 抽象工厂模式&#xff1a; 代码实现&#xff1a; #include <stdio.h>// 定义抽象产品接口 typedef struct {void (*operation)(); } AbstractProductA;typedef struct {voi…

智慧工地管理系统加快推进工程建设项目全生命周期数字化

智慧工地管系统是一种利用人工智能和物联网技术来监测和管理建筑工地的系统。它可以通过感知设备、数据处理和分析、智能控制等技术手段&#xff0c;实现对工地施工、设备状态、人员安全等方面的实时监控和管理。 智慧工地以物联网、移动互联网技术为基础&#xff0c;充分应用大…

WPF面试题:WPF绘图技术介绍

作者:令狐掌门 技术交流QQ群:675120140 csdn博客:https://mingshiqiang.blog.csdn.net/ 文章目录 WPF绘图基本用法绘制直线在XAML中绘制直线在C#代码中绘制直线使用Path绘制直线注意矩形绘制在XAML中绘制矩形在C#代码中绘制矩形设置矩形的位置使用圆角矩形画刷1. SolidColor…

Go 中切片(Slice)的长度与容量

切片长度与容量在 Go 中很常见。切片长度是切片中可用元素的数量&#xff0c;而切片容量是从切片中第一个元素开始计算的底层数组中的元素数量。 Go 中的开发者经常混淆切片长度和容量&#xff0c;或者对它们不够了解。理解这两个概念对于高效处理切片的核心操作&#xff0c;比…

“AI+量子模拟”突破!英伟达与美国量子技术公司SandboxAQ合作

&#xff08;图片来源&#xff1a;网络&#xff09; 11月20日&#xff0c;美国量子技术公司SandboxAQ在美国加利福尼亚州帕洛阿尔托宣布与美国人工智能计算公司英伟达&#xff08;NVIDIA&#xff09;联手&#xff0c;双方将通过人工智能和量子模拟技术助力药物发现、电池设计、…

ESP32-Web-Server编程-HTML 基础

ESP32-Web-Server编程-HTML 基础 概述 HTML(HyperText Markup Language) 是用来描述网页的一种语言。其相关内容存储在前端代码的 .html 文件中。 当浏览器向 web 服务器请求网页时&#xff0c;一个 HTML 文件被发送给浏览器&#xff0c;浏览器解释该文件的内容&#xff0c;…

ASP.NET Core Web API设置响应输出的Json数据格式的两种方式

前言 在ASP.NET Core Web API中设置响应输出Json数据格式有两种方式&#xff0c;可以通过添加System.Text.Json或Newtonsoft.JsonJSON序列化和反序列化库在应用程序中全局设置接口响应的Json数据格式&#xff0c;本文示例使用的是新的Minimal API模式。 JSON序列化和反序列化库…

【TinyALSA全解析(二)】wav和pcm音频文件格式详解

wav和pcm音频文件格式详解 一、本文的目的二、wav和pcm格式文件介绍三、pcm格式文件解析四、wav文件内容解析4.1 文件内容描述4.2 实战分析 五、如何在各种音频格式之间进行转换 /******************************************************************************************…

TikTok数据分析:如何通过数字洞察提升内容质量?

引言 TikTok作为全球最热门的短视频平台之一&#xff0c;每天吸引着亿万用户发布和观看各类内容。在这个充满创意的舞台上&#xff0c;内容质量成为吸引关注和提高曝光度的关键。 而要达到这一目标&#xff0c;数字数据分析成为不可或缺的工具。本文将深入探讨如何通过TikTok数…

为什么需要配置中心

将所有配置放在配置中心&#xff0c;例如Nacos中&#xff0c;有以下几个原因&#xff1a; 集中管理&#xff1a;将配置集中存储在一个地方可以方便管理和维护。通过配置中心&#xff0c;我们可以集中查看、修改和删除配置&#xff0c;而无需去每个应用程序中逐个修改配置文件。…

AI - Steering behaviors(转向系统)

游戏AI角色的转向系统&#xff08;Steering behaviors&#xff09;实现 一些向量的接口是cocos2dx的。但从名字上应该能理解做了什么向量操作 Seek&#xff1a; 获取当前位置指向目标点的向量&#xff0c;转化为单位向量后再乘以速度值&#xff0c;即为所需速度desired velo…

【C语言】结构体

目录 1. 前言2. 结构体类型的声明2.1 结构体的概念2.2 结构的创建2.3 特殊的声明2.4 结构的自引用 3. 结构成员访问操作符4. 结构体内存对齐4.1 对齐规则4.2 为什么存在内存对齐&#xff1f;4.3 修改默认对齐数 5. 结构体传参6. 结构体实现位段6.1 什么是位段6.2 位段的内存分配…

Android系统源码中,在手上没有源码的情况下,需要将编译好的二进制可执行文件放入系统中

文章目录 Android系统源码中&#xff0c;在手上没有源码的情况下&#xff0c;需要将编译好的二进制可执行文件放入系统中 Android系统源码中&#xff0c;在手上没有源码的情况下&#xff0c;需要将编译好的二进制可执行文件放入系统中 在Android.bp文件中&#xff0c;然后整编…

[ACTF2020 新生赛]BackupFile

打开题目就一句话&#xff1a;尝试找到源文件 和上一题一样&#xff0c;用dirsearch扫描网站找到了一下内容 flag.php&#xff0c;0B&#xff0c;虚假flag 瞅一眼index.php.bak是啥 下载了一个文件&#xff0c;把bak后缀删掉&#xff0c;打开了index.php源码 is_numeric()&am…

成为AI产品经理——模型评估(混淆矩阵)

一、混淆矩阵 1.混淆矩阵的介绍 混淆矩阵有两个定义positive&#xff08;正例&#xff09;和negative&#xff08;反例&#xff09;。分别代表模型结果的好和坏。 下图就是一个分类问题的混淆矩阵。横行代表真实的情况&#xff0c;而竖行代表预测的结果。 为了便于理解&…

新疆大学与优艾智合机器人成立联合创新实验室

11月22日至24日&#xff0c;第五届中国工业互联网大赛新疆赛站决赛在新疆维吾尔自治区昌吉回族自治州昌吉市举行。在大赛中崭露头角的优秀解决方案&#xff0c;将为绿色工厂、绿色园区、绿色供应链等建设提供新的动能&#xff0c;促进工业绿色发展。 作为大赛的成果延伸&#…

面试常问-如何判断链表有环、?

如何判断链表有环 题目&#xff1a;解决方案一&#xff1a;解决方案二&#xff1a;解决方案三&#xff1a; 题目&#xff1a; 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;…

MSB3541 Files 的值“<<<<<<< HEAD”无效。路径中具有非法字符。

MSB3541 Files 的值“<<<<<<< HEAD”无效。路径中具有非法字符。 一般来说出现这个问题是因为使用git版本控制工具合并代码出现了问题&#xff0c;想要解决也很简单。 如图点击错误后定位到文件&#xff0c;发现也没有什么问题。 根据错误后边的提示&a…