做网站用到的技术广告公司怎么做

pingmian/2025/10/8 1:31:12/文章来源:
做网站用到的技术,广告公司怎么做,江苏网站seo营销模板,如何做网站对比创建型 单例模式 Singleton#xff1a;确保一个类只有一个实例#xff0c;并提供该实例的全局访问点 使用一个私有构造方法、一个私有静态变量以及一个公有静态方法来实现。私有构造方法确保了不能通过构造方法来创建对象实例#xff0c;只能通过公有静态方法返回唯一的私…创建型 单例模式 Singleton确保一个类只有一个实例并提供该实例的全局访问点 使用一个私有构造方法、一个私有静态变量以及一个公有静态方法来实现。私有构造方法确保了不能通过构造方法来创建对象实例只能通过公有静态方法返回唯一的私有静态变量。 懒汉式-线程不安全私有静态变量被延迟实例化在多线程环境下不安全可能多次实例化 public class Singleton {private static Singleton uniqueInstance;private Singleton() {}public static Singleton getUniqueInstance() {if (uniqueInstance null) {uniqueInstance new Singleton();}return uniqueInstance;}} 饿汉式-线程安全采取直接实例化的方式就不会产生线程不安全的问题 private static Singleton uniqueInstance new Singleton(); 懒汉式-线程安全只需要对getUniqueInstance()方法加锁那么在一个时间点只能有一个线程能够进入该方法从而避免了实例化多次uniqueInstance。但是当一个线程进入后其他线程必须等待即使对象已经被实例化这会让阻塞时间过长因此该方法有性能问题。 public static synchronized Singleton getUniqueInstance() {if (uniqueInstance null) {uniqueInstance new Singleton();}return uniqueInstance; } 双重校验锁-线程安全对象只需要被实例化一次之后就可以直接使用了。加锁操作只需要对实例化部分的代码进行只有当uniqueInstance没有被实例化时才需要进行加锁。双重校验锁先判断uniqueInstance是否已经被实例化如果没有被实例化那么才对实例化语句进行加锁。 public static getUniqueInstance() {if (null uniqueInstance) {synchronized(Singleton.class) {if (null uniqueInstance) {uniqueInstance new Singleton();}}} } uniqueInstance采用volatile关键字修饰也是很有必要的uniqueInstance new Singleton();这段代码其实是分三步执行 为uniqueInstance分配内存空间初始化uniqueInstance将uniqueInstance指向分配的内存地址 ‼️ 由于JVM具有指令重排的特性执行顺序有可能变成132。指令重排在单线程环境下不会出现问题但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如线程T1执行了1和3此时T2调用getUniqueInstance()后发现uniqueInstance不为空因此返回uniqueInstance但此时uniqueInstance还未被初始化。 使用volatile可以禁止JVM的指令重排保证在多线程环境下也能正常运行 静态内部类实现当Singleton类被加载时静态内部类SingletonHolder没有被加载进内存。只有当调用getUniqueInstance()方法从而触发SingletonHolder.INSTANCE时SingletonHolder才会被加载此时初始化INSTANCE实例并且JVM能确保INSTANCE只被实例化一次。 public class Singleton() {private Singleton(){}private static class SingletonHolder() {private static final Singleton INSTANCE new Singleton();}public static Singleton getUniqueInstance() {return SingletonHolder.INSTNACE;} }枚举实现可以防止反射攻击。在其他实现中通过setAccessible()方法可以将私有构造方法的访问级别设置为public然后调用构造方法从而实例化对象如果要防止这种攻击需要在构造方法中添加防止多次实例化的代码。该实现是由JVM保证之后实例化一次因此不会出现上述的反射攻击。该实现在多次序列化和反序列化之后不会得到多个实例。而其他实现需要使用transient修饰所有字段并且实现序列化和反序列化的方法。 public enum Singleton {INSTANCE;private String objName;public String getObjName(){return objName;}public void setObjName(String objName) {this.objName objName;} } 简单工厂 Simple Factory在创建一个对象时不向客户暴露内部细节并提供一个创建对象的通用接口 简单工厂把实例化的操作单独放到一个类这个类就成为简单工厂类让简单工厂类来决定应该用哪个具体子类来实例化。这样做能把客户类和具体子类的实现解耦客户类不再需要知道有哪些子类以及应当实例化哪个子类。客户类往往有多个如果不使用简单工厂那么所有的客户类都要知道所有子类的细节。而且一旦子类发生改变例如增加子类那么所有的客户类都要进行修改。 public class SimpleFactory {public Product createProduct(int type) {if (type 1)return new ConcreateProduct1();else if (type 2) return new ConcreateProduct2();return new ConcreateProduct3();} }public class Client {public static void main(String[] args) {SimpleFactory f new SimpleFactory();Product p f.createProduct(1);} } 工厂方法 Factory Method定义了一个创建对象的接口但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。 在简单工厂中创建对象的是另一个类而在工厂方法中是由子类来创建对象。下图中Factory有一个doSomething方法这个方法需要用到一个产品对象这个产品对象由factoryMethod方法创建。该方法是抽象的需要由子类去实现。 public abstract class Factory {abstract public Product factoryMethod();public void doSomething(){// } }public class ConcreateFactory extend Factory {public Product factoryMethod() {return new ConcreateProduct();} } public class ConcreateFactory1 extends Factory {public Product factoryMethod() {return new ConcreateProduct1();} } 抽象工厂 Abstract Factory提供一个接口用于创建相关的对象家族 抽象工厂模式创建的是对象家族也就是很多对象而不是一个对象并且这些对象是相关的也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象这和抽象工厂模式有很大不同。抽象工厂模式用到了工厂方法模式来创建单一对象AbstractFactory中的createProductA()和createProductB()方法都是让子类来实现这两个方法单独来看就是在创建一个对象这符合工厂方法模式的定义。 至于创建对象的家族这一概念是在Client体现Client要通过AbstractFactory同时调用两个方法来创建出两个对象在这里这两个对象就有很大的相关性Client需要同时创建出这两个对象。从高层次来看抽象工厂使用了组合即Client组合了AbstractFactory而工厂方法模式使用了继承。 public class AbstractProductA { }public class AbstractProductB { }public class ProductA1 extends AbstractProductA { }public class ProductA2 extends AbstractProductA { }public class ProductB1 extends AbstractProductB { }public class ProductB2 extends AbstractProductB { }public abstract class AbstractFactory {abstract AbstractProductA createProductA();abstract AbstractProductB createProductB(); }public class ConcreteFactory1 extends AbstractFactory {AbstractProductA createProductA() {return new ProductA();}AbstractProductB createProductB() {return new ProductB();} }public class ConcreteFactory2 extends AbstractFactory {AbstractProductA createProductA() {return new ProductA();}AbstractProductB createProductB() {return new ProductB();} }public class Client {public static void main(String[] args) {AbstractFactory af new ConcreateFactory1();AbstractProductA a af.createProductA();AbstractProductB b af.createProductB();} } 生成器模式 Builder封装一个对象的构造过程并允许按步骤构造 将一个复杂对象的构建与它的表示分离使得同样的构建过程可以创建不同的表示。 Product 产品类通常是实现了模板方法模式也就是有模板方法和基本方法Builder 抽象建造者规范产品的组件一般是由子类实现。ConcreteBuilder 具体建造者实现抽象类定义的所有方法并且返回一个组建好的对象Director 导演类负责安排已有模块的顺序就会告诉Builder开始建造使用场景 相同的方法不同的执行顺序产生不同的事件结果时可以采用建造者模式多个部件或零件都可以装配到一个对象中但是产生的运行结果又不相同时则可以使用该模式产品类非常复杂或者产品类中的调用顺序不同产生了不同的效能这个时候使用建造者模式非常合适 与抽象工厂的区别在生产者模式里有个指导者由指导者来管理生产者用户是与指导者联系的指导者联系生产者最后得到产品。即生产者模式可以强制实行一种分步骤进行的建造过程。与工厂模式的区别建造者模式最主要的功能是基本方法的调用顺序安排这些基本方法已经实现了顺序不同产生的对象也不同。工厂方法则重点是创建创建零件是他的主要职责组装顺序则不是他关心的 以下是简易的StringBuilder实现参考了JDK8源码 public class AbstractStringBuilder {protected char[] value;protected int count;public AbstractStringBuilder(int capacity) {count 0;value new char[capacity];}public AbstractStringBuilder append(char c) {ensureCapacityInternal(count 1);value[count] c;return this;}private void ensureCapacityInternal(int minimumCapacity) {if (minimumCapacity - value.length 0) {expandCapacity(minimumCapacity);}}void expandCapacity(int minimumCapacity) {int newCapacity value.length * 2 2;if (newCapacity - minimumCapacity 0) {newCapacity minimumCapacity;}if (newCapacity 0) {if (minimumCapacity 0) {throw new OutOfMemoryError();}newCapacity Integer.MAX_VALUE;}} }public class StringBuilder extends AbstractStringBuilder {public StringBuilder() {super(16);}Overridepublic String toString() {return new String(value, 0, count);} }public class Client {public static void main(String[] args) {StringBuilder sb new StringBuilder();final int count 20;for (int i 0; i count; i) {sb.append((char)(ai));}System.out.println(sb.toString());} } 原型模式 Prototype使用原型实例指定要创建对象的类型通过复制这个原型来创建新的对象 原型模式主要用于对象的复制它的核心就是类图中的原型类Prototype。Prototype类需要具备以下两个条件 实现Cloneable接口。在java语言有一个Cloneable接口它的作用只有一个就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中只有实现了这个接口的类才可以被拷贝否则在运行时会抛出CloneNotSupportedException异常。 重写Object类的clone方法。java中所有类的父类都是Object类Object类有一个clone方法作用是返回对象的一个拷贝但是其作用域protected类型的一般的类无法调用因此Prototype类需要将clone方法的作用域修改为public类型。 优点 性能优良 原型模式是在内存二进制流的拷贝要比直接new一个对象性能好很多特别是要在一个循环体内产生大量的对象时原型模式可以更好地体现其优点 逃避构造函数的约束 既是优点也是缺点直接在内存中拷贝构造函数是不会执行的 使用场景 资源优化场景 类初始化需要消化非常多的资源这个资源包括数据、硬件资源等 性能和安全要求的场景 通过new产生一个对象需要非常繁琐的数据准备或访问权限则可以使用原型模式 一个对象多个修改者的场景 一个对象需要提供给其他对象访问而且各个调用者可能都需要修改其值时可以考虑使用原型模式拷贝多个对象供调用者使用 public class PrototypeClass implements Cloneable{ // 覆写父类 Object 方法Overridepublic PrototypeClass clone() { PrototypeClass prototypeClass null; try {prototypeClass (PrototypeClass)super.clone(); } catch (CloneNotSupportedException e) {//异常处理}return prototypeClass;} } 行为型 责任链 Chain Of Responsibility使多个对象都有机会处理请求从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链并沿着这条链发送该请求直到有一个对象处理它为止。 责任链模式结构的重要核心模块 Handler 抽象处理者 定义一个处理请求的接口一般设计为抽象类由于不同的具体处理者处理请求的方式不同因此在其中定义了抽象请求处理方法。因为每一个处理者的下家还是一个处理者因此在抽象处理者定义了一个抽象处理者类型的对象作为其对下家的引用。通过该引用处理者可以连成一条链。 请求的处理方法 handleMessage唯一对外开放的方法链的编排方法 setNext设置下一个处理者具体的请求者必须实现的两个方法定义自己能够处理的级别 getHandlerLevel 和具体的处理任务 echo 链中的节点数量需要限制避免出现超长链的情况一般的做法是在Handler中设置一个最大节点数量在setNext方法中判断是否已经是超过其阈值超过则不允许该链建立避免无意识地破坏系统性能 ConcreteHandler 具体处理者 抽象处理者的子类可以处理用户请求在具体处理者类中实现了抽象处理者中定义的抽象请求处理方法在处理请求之前需要进行判断看是否有相应的处理权限如果可以处理请求就处理它否则将请求转发给后继者在具体处理者中可以访问链中下一个对象以便请求的转发。 public abstract class Handler {private Handler nextHandler;//每个处理者都必须对请求做出处理public final Response handleMessage(Request request) {Response response null;//判断是否是自己的处理级别if(this.getHandlerLevel().equals(request.getRequestLevel())) { response this.echo(request);} else { //不属于自己的处理级别//判断是否有下一个处理者if(this.nextHandler ! null) {response this.nextHandler.handleMessage(request);} else {//没有适当的处理者业务自行处理}}return response;}// 设置下一个处理者是谁public void setNext(Handler _handler) { this.nextHandler _handler;}// 每个处理者都有一个处理级别protected abstract Level getHandlerLevel(); // 每个处理者都必须实现处理任务protected abstract Response echo(Request request); } 命令 Command将一个请求封装成一个对象从而让你使用不同的请求把客户端参数化对请求排队或者记录请求日志可以提供命令的撤销和恢复功能 使用命令来参数化其他对象将命令放入队列中进行排队将命令的操作记录到日志中支持可撤销的操作 下面说一下关键的一些类 Command类是一个抽象类类中对需要执行的命令进行声明一般来说要对外公布一个execute方法用来执行命令ConcreteCommane类Command类的实现类对抽象类中声明的方法进行实现Client类最终的客户端调用类Invoker类调用者负责调用命令Receiver类接收者负责接收命令并且执行命令 public interface Command {void execute(); }public class LightOnCommand implements Command {Light light;public LightOnCommand(Light light) {this.light light;}Overridepublic void execute() {light.on();} }public class LightOffCommand implements Command {Light light;public LightOffCommand(Light light) {this.light light;}Overridepublic void execute(){light.off();} }public class Light {public void on() {System.out.println(light is on);}public void off() {System.out.println(light is off);} }public class Invoker {private Command[] onCommands;private Command[] offCommands;;private final int slotNum 7;public Invoker() {this.onCommands new Command[slotNum];this.offCommands new Command[slotNum];}public void setOnCommand(Command command, int slot) {onCommands[slot] command;}public void setOffCommand(Command command, int slot) {offCommands[slot] command;}public void onButtonWasPushed(int slot) {onCommands[slot].execute();}public void offButtonWasPushed(int slot) {offCommands[slot].execute();} }public class Client {public static void main(String[] args) {Invoker invoker new Invoker();Light light new Light();Command lightOnCommand new LightOnCommand(light);Command lightOffCommand new LightOffCommand(light);invoker.setOnCommand(lightOnCommand, 0);invoker.setOffCommand(lightOffCommand, 0);invoker.onButtonWasPushed(0);invoker.offButtonWasPushed(0);} }解释器 Interpreter为语言创建解释器通常由语言的语法和语法分析来定义少用 TerminalExpression终结符表达式每个终结符都需要一个TerminalExpressionContext上下文包含解释器之外的一些全局信息 以下是一个规则检验器实现具有and和or规则通过规则可以构建一颗解析树用来检验一个文本是否满足解析树定义的规则。 public abstract class Expression {public abstract boolean interpret(String str); }public class TerminalExpression extends Expression {private String literal null;public TerminalExpression(String str) {literal str;}public boolean interpret(String str) {StringTokenizer st new StringTokenizer(str);while(st.hasMoreTokens) {String test st.nextToken();if (test.equals(literal)){return true;}}return false;} }public class AndExpression extends Expression {private Expression expression1 null;private Expression expression2 null;public AndExpression(Expression expression1, Expression expression2) {this.expression1 expression1;this.expression2 expression2;}public boolean interpret(String str){return expression1.interpret(str) expression2.interpret(str);} }public class OnExpression extends Expression {private Expression expression1 null;private Expression expression2 null;public OrExpression(Expression expression1, Expression expression2) {this.expression1 expression1;this.expression2 expression2;}public boolean interpret(String str) {return expression1.interpret(str) || expression2.interpret(str);} }public class Client {public static Expression buildInterpreterTree() {Expression e1 new TerminalExpression(A);Expression e2 new TerminalExpression(B);Expression e3 new TerminalExpression(C);Expression e4 new TerminalExpression(D);Expression a1 new OrExpression(e2, e3);Expression a2 new OrExpression(e1, a1);return new AndExpression(e4, a2);} } 迭代器 Iterator提供一种顺序访问聚合对象元素的方法并且不暴露聚合对象的内部表示。该模式已经被淘汰Java中已经把迭代器运用到各个聚集类中了使用java自带的迭代器已经满足我们的需求了 Aggregate 是聚合类其中createIterator()方法可以产生一个IteratorIterator 主要定义了hasNext()和next()方法Client 组合了Aggregate为了迭代遍历Aggregate也需要组合Iterator public interface Aggregate {Iterator createIterator(); }public class ConcreteAggregate implements Aggregate {private Integer[] items;public ConcreteAggregate() {items new Integer[10];for (int i 0; i items.length; i) {items[i] i;}}Overridepublic Iterator createIterator() {return new ConcreteIteratorInteger(items);} }public interface IteratorItem {Item next();boolean hasNext(); }public class ConcreteIteratorItem implements Iterator {private Item[] items;private int position 0;public ConcreteIterator(Item[] items) {this.items items;}Overridepublic Object next() {return items[position];}Overridepublic boolean hasNext() {return position items.length;} }public class Client {public static void main(String[] args) {Aggregate aggregate new ConcreteAggregate();IteratorInteger it aggregate.createIterator();while(iterator.hasNext()){System.out.println(iterator.next());}} }中介者 Mediator用一个中介对象封装一系列的对象交互中介者使各对象不需要显示地相互作用从而使其耦合松散而且可以独立地改变它们之间的交互 Mediator抽象中介者定义统一接口用于与各同事(Colleague)对象通信Concrete Mediator具体中介者通过协调各同事角色实现协作行为因此它必须依赖于各个同事角色Colleague 同事每个同事角色都知道中介者角色而且与其他的同事角色通信的时候一定要通过中介者角色协作。每个同事类地行为分为两种 一种是同事本身的行为比如改变对象本身的状态处理自己的行为等这种行为叫做自发行为Self-Method与其他的同事类或中介者没有任何的依赖一种是必须依赖中介者才能完成的行为叫做依赖方法Dep-Method 使用场景 适用于多个对象之间紧密耦合的情况紧密耦合的标准是在类图中出现了蜘蛛网状结构即每个类都与其他的类有直接的联系 一般来说同事类之间的关系是比较复杂的多个同事类之间互相关联时他们之间的关系会呈现为复杂的网状结构这是一种过度耦合的架构不利于类的复用也不稳定。如果引入中介者模式那么同事类之间的关系将变为星型结构任何一个类的变动只会影响本身以及中介者这样就减小系统的耦合。一个好的设计必定不会把所有的对象关系处理逻辑封装在本类中而是使用一个专门的类来管理那些不属于自己的行为。 public abstract class Mediator {//定义同事类protected ConcreteColleague1 c1;protected ConcreteColleague2 c2;//通过 getter/setter 方法把同事类注入进来public ConcreteColleague1 getC1() {return c1;}public void setC1(ConcreteColleague1 c1) { this.c1 c1;}public ConcreteColleague2 getC2() {return c2;}public void setC2(ConcreteColleague2 c2){ this.c2 c2;}//中介者模式的业务逻辑public abstract void doSomething1();public abstract void doSomething2(); }使用同事类注入而不使用抽象注入的原因是因为抽象类中不具有每个同事类必须要完成的方法。即每个同事类中的方法各不相同为什么同事类要使用构造函数注入中介者而中介者使用 getter/setter 方式注入同事类呢 因为同事类必须有中介者而中介者却可以只有部分同事类 备忘录 Memento在不违反封装的情况下获得对象的内部状态从而在需要时可以将对象恢复到最初状态。 使用场景 需要保存和恢复数据的相关状态场景提供一个可回滚的操作需要监控的副本场景中数据库连接的事务管理就是用的备忘录模式 注意 备忘录的生命周期备忘录的性能 不要在频繁建立备份的场景中使用备忘录模式比如一个for循环 Originator原始对象Caretaker负责保存好备忘录Memento备忘录存储原始对象的状态。备忘录实际上有两个接口一个是提供给Caretaker的窄接口它只能将备忘录传递给其他对象一个是提供给Originator的宽接口允许它访问到先前状态所需的所有数据。理想情况是只允许Originator访问本备忘录的内部状态。 以下实现了一个简单计算器程序可以输入两个值然后计算两个值的和备忘录模式允许将这两个值存储起来然后在某个时刻用储存的状态进行恢复。 public interface Calculator {PreviousCalculationToCareTaker backupLastCalculation();void restorePreviousCalculatoin(PreviousCalculationToCareTaker memento);int getCalculationResult();void setFirstNumber(int firstNumber);void setSecondNumber(int secondNumber); }public class CalcuatorImp implemnets Calculator {private int firstNumber;private int secondNumber;Overridepublic PreviousCalculationToCareTaker backupLastCalculation() {return new PreviousCalculationImp(firstNumber, secondNumber);}Overridepublic void restorePreviousCalculation(PreviousCalculationToCareTaker memento) {this.firstNumber ((PreviousCalculationToOriginator)memento).getFirstNumber();this.secondNumber ((PreviousCalculationToOriginator)memento).getSecondNumber();} }public interface PreviousCalculationToCareTaker { }public class PreviousCalculationImp implements PreviousCalculationToCareTaker, PreviousCalculationToOriginator {private int firstNumber;private int secondNumber;public PreviousCalculationImp(int firstNumber, int secondNumber) {this.firstNumber firstNumber;this.secondNumber secondNumber;}Overridepublic int getFirstNumber() {return firstNumber;}Overridepublic int getSecondNumber() {return secondNumber;} }public class Client {public static void main() {Calculator calculator new Calculator();calculator.setFirstNumber(10);calculator.setSecondNumber(100);System.out.println(calculator.getCalculationResult());PreviousCalculationToCareTaker memento calculator.backupLastCalculation();calculator.setFirstNumber(17);calculator.setSecondNumber(-290);System.out.println(calculator.getCalculationResult());calculator.restorePreviousCalculation(memento);System.out.println(calculator.getCalculationResult());} }观察者 Observer定义对象之间的一对多依赖当一个对象状态改变时它的所有依赖都会收到通知并且自动更新状态。 使用场景 关联行为场景。需要注意的是关联行为是可拆分的不是组合关系事件多级触发场景跨系统的消息交换场景如消息队列的处理机制 注意 广播链的问题 在一个观察者模式中最多出现一个对象既是观察者也是被观察者也就是说消息最多转发一次传递两次 异步处理问题 观察者比较多而且处理时间比较长采用异常处理来考虑线程安全和队列的问题 主题是被观察的对象而其所有依赖者称为观察者。主题具有注册和移除观察者、并通知所有观察者的功能主题是通过维护一张观察者列表来实现这些操作的。观察者的注册功能需要调用主题的registerObserver()方法。 public interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObserver(Observer o); }public class WeatherData implements Subject {private ListObserver observers;private float temperature;private float humidity;private float pressure;public WeacherData() {observers new ArrayList();}public void setMeasurements() {this.temperature temperature;this.humidity humidity;this.pressure pressure;notifyObserver();} Overridepublic void registerObserver(Observer o) {observers.add(o);}Overridepublic void removeObserver(Observer o) {int i observers.indexOf(o);if (i 0) {observers.remove(i);}}Overridepublic void notifyObserver() {for (Observer o : observers) {o.update(temperature, humidity, pressure);}} }public interface Observer {void update(float temp, float humidity, float pressure); }public class StatisticsDisplay implements Observer {public StatisticsDisplay(Subject weacherData) {weacherData.registerObserver(this);}Overridepublic void update(float temp, float humidity, float pressure) {System.out.println(StatisticsDisplay.update: temp humidity pressure);} }public class CurrentConditionsDisplay implements Observer {public CurrentConditionsDisplay(Subject weacherData) {weacherData.registerObserver(this);}Overridepublic void update(float temp, float humidity, float pressure) {System.out.println(CurrentConditionsDisplay.update: temp humidity pressure);} }public class WeacherStation {public static void main(String[] args) {WeatherData weatherData new WeatherData();CurrentConditionsDisplay currentConditionsDisplay new CurrentConditionsDisplay();StatisticsDisplay statisticsDisplay new StatisticsDisplay(weatherData);weatherData.setMeasurements(0, 0, 0);weatherData.setMeasurements(1, 1, 1);} }状态 state 允许对象在内部状态改变时改变它的行为对象看起来好像修改了它所属的类。 使用场景 行为随状态改变而改变的场景 也是状态模式的根本出发点例如权限设计人员的状态不同即使执行相同的行为结果也会不同在这种情况下需要考虑使用状态模式 条件、分支判断语句的替代者 注意 状态模式适用于当某个对象在它的状态发生改变时它的行为也随着发生比较大的变化也就是说在行为受约束的情况下可以使用状态模式而且使用时对象的状态最好不要超过5个 糖果销售机有多种状态每种状态下销售机有不同的行为状态可以发生转移使得销售机的行为也发生改变。 public interface State {void insertQuarter();void ejectQuarter();void turnCrank();void dispense(); } public class GumballMachine {private State soldOutState;private State noQuarterState;private State hasQuarterState;private State soldState;private State state;private int count 0;public GumballMachine(int numberGumballs) {count numberGumballs;soldOutState new SoldOutState(this);noQuarterState new NoQuarterState(this);hasQuarterState new HasQuarterState(this);soldState new SoldState(this);if (numberGumballs 0) {state noQuarterState;} else {state soldQuarterState;}}public void insertQuarter() {state.insertQuarter();}public void ejectQuarter() {state.ejectQuarter();}public void turnCrank() {state.turnCrank();}public void setState(State state) {this.state state;}public void releaseBall() {System.out.println(A gumball comes rolling out the slot ...);if (count ! 0) {count - 1;}}public State getSoldOutState() {return soldOutState;}public State getNoQuarqterState() {return noQuarterState;}public State getHasQuarterState() {return hasQuarterState;}public State getSoldState() {return soldState;}public int getCount() {return count;} }public class HasQuarterState implements State {private GumballMachine gumballMachine;public HasQuarterState(GumballMachine gumballMachine) {this.gumballMachine gumballMachine;}Overridepublic void insertQuarter() {System.out.println(You cant insert another quarter);}Overridepublic void ejectQuarter() {System.out.println(Quarter returned);gumballsMachine.setState(gumballMachine.getNoQuarterState());}Overridepublic void turnCrank() {System.out.println(You turned ...);gumballMachine.setState(gumballMachine.getSoldState());}Overridepublic void dispense() {System.out.println(No gumball dispensed);} }public class NoQuarterState implements State {// ... }public class SoldOutState implements State {// ... }public class SoldState implements State {// ... }public class Client {GumballMachine gumballMachine new GumballMachine(5);gumballMachine.insertQuarter();gumballMachine.turnCrank();gumballMachine.insertQuarter(); }策略 Strategy 定义一系列算法封装每个算法并使它们可以互换。策略模式可以让算法独立于使用它的客户端。 Strategy 抽象策略角色 接口定义了一个算法族它们都实现了behavior方法 Context 封装角色 是使用到该算法族的类其中的doSomething方法会调用behaviorsetStrategy(Strategy)方法可以动态地改变strategy对象也就是说能动态地改变Context所使用的算法。 Concrete Strategy 具体策略角色多个 实现抽象策略中的操作该类含有具体的算法 使用场景 多个类只有在算法或行为上稍有不同的场景算法需要自有切换的场景需要屏蔽算法规则的场景 状态模式的类图和策略模式类似并且都是能够动态改变对象的行为。但是状态模式是通过状态转移来改变Context所组合的State对象而策略模式是通过Context本身的决策来改变组合的Strategy对象。所谓的状态转移是指Context在运行过程中由于一些条件发生改变而使得State对象发生改变注意必须要是在运行过程中。 状态模式主要是用来解决状态转移的问题当状态发生转移了那么Context对象就会改变它的行为而策略模式主要是用来封装一组可以互相替代的算法族并且可以根据需要动态地去替换Context使用的算法。 设计一个鸭子它可以动态地改变叫声这里的算法族是鸭子的叫声行为。 public interface QuackBehavior {void quack(); }public class Quack implements QuackBahavior {Overridepublic void quack() {System.out.println(quack!);} }public class Squeak implements QuackBehavior {Overridepublic void quack() {System.out.println(squeak!);} }public class Duck {private QuackBehavior quackBehavior;public void performQuack() {if (quackBehavior ! null) {quackBehavior.quack();}}public void setQuackBehavior(QuackBehavior quackBehavior) {this.quackBehavior quackBehavior;} }public class Client {public static void main(String[] args) {Duck duck new Duck();duck.setQuackBehavior(new Squeak());duck.performQuack();duck.setQuackBehavior(new Quack());duck.performQuack();} }模板方法 Template Method **定义算法框架并将一些步骤的实现延迟到子类。通过模板方法子类可以重新定义算法的某些步骤而不用改变算法的结构。 ** 方法分为两类 基本方法也叫做基本操作是由子类实现的方法并且在模板方法被调用模板方法可以有一个或几个一般是一个具体方法也就是一个框架实现对基本方法的调度完成固定的逻辑 为了防止恶意操作一般模板方法都加上final关键字不允许被覆写 使用场景 多个子类有共有的方法并且逻辑基本相同时重要、复杂的算法可以把核心算法设计为模板方法周边的相关细节功能则由各个子类实现重构时模板方法模式是一个经常使用的模式把相同的代码抽取到父类中然后通过钩子函数约束其行为 冲咖啡和冲茶都有类似的流程但是因为某些步骤会有点不一样要求复用那些相同步骤的代码。 public abstract class CaffeineBeverage {final void prepareRecipe() {boilWater();brew();pourInCup();addCondiments();}abstract void brew();abstract void addCondiments();void boilWater() {System.out.println(boilWater);}void pourInCup() {System.out.println(pourInCup);} }访问者 visitor 封装一些作用于某种数据结构中的各元素的操作它可以在不改变数据结构的前提下定义作用于这些元素的新的操作 Visitor访问者抽象类或接口声明访问者可以访问哪些元素为每一个ConcreteElement声明一个visit操作该方法参数定义哪些对象是可以被访问的ConcreteVisitor具体访问者它影响访问者访问到一个类后该怎么干要做什么事情Element抽象元素接口或抽象类声明接受哪一类访问者访问程序上是通过accept方法中的参数来定义Concrete Element具体元素实现 accept 方法通常是 visitor.visit(this)基本上都形成了一种模式Object Structure对象结构可以是组合结构或者是一个集合元素产生者一般容纳在多个不同类、不同接口的容器如 List、Set、Map 等在项目中一般很少抽象出这个角色 使用场景 一个对象结构包含很多类对象它们有不同的接口而你想对这些对象实施一些依赖于其具体类的操作也就是说用迭代器模式已经不能胜任的情景需要对一个对象结构中的对象进行很多不同并且不相关的操作而你想避免让这些操作污染这些对象的类 public interface Element {void accept(Visitor visitor); } class CustomerGroup {private ListCustomer customers new ArrayList();void accept(Visitor visitor) {for (Customer customer : customers) {customer.accept(visitor);}}void addCustomer(Customer customer) {customers.add(customer);} } public class Customer implements Element {private String name;private ListOrder orders new ArrayList();Customer(String name) {this.name name;}String getName() {return name;}void addOrder(Order order) {orders.add(order);}public void accept(Visitor visitor) {visitor.visit(this);for (Order order : orders) {order.accept(visitor);}} } public class Order implements Element {private String name;private ListItem items new ArrayList();Order(String name) {this.name name;}Order(String name, String itemName) {this.name name;this.addItem(new Item(itemName));}String getName() {return name;}void addItem(Item item) {items.add(item);}public void accept(Visitor visitor) {visitor.visit(this);for (Item item : items) {item.accept(visitor);}} } public class Item implements Element {private String name;Item(String name) {this.name name;}String getName() {return name;}public void accept(Visitor visitor) {visitor.visit(this);} } public interface Visitor {void visit(Customer customer);void visit(Order order);void visit(Item item); } public class GeneralReport implements Visitor {private int customersNo;private int ordersNo;private int itemsNo;public void visit(Customer customer) {System.out.println(customer.getName());customersNo;}public void visit(Order order) {System.out.println(order.getName());ordersNo;}public void visit(Item item) {System.out.println(item.getName());itemsNo;}public void displayResults() {System.out.println(customersNo);System.out.println(itemsNo);System.out.println(ordersNo);} }public class Client {public static void main(String[] args) {Customer customer1 new Customer(customer1);customer1.addOrder(new Order(order1, item1));customer1.addOrder(new Order(order2, item1));customer1.addOrder(new Order(order3, item1));Order order new Order(order_a);order.addItem(new Item(item_a1));order.addItem(new Item(item_a2));order.addItem(new Item(item_a3));Customer customer2 new Customer(customer2);customer2.addOrder(order);CustomerGroup customers new CustomerGroup();customers.addCustomer(customer1);customers.addCustomer(customer2);GeneralReport visitor new GeneralReport();customers.accept(visitor);visitor.displayResults();} }结构型 适配器 Adapter 将一个类的接口变换成客户端所期待的另一种接口从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作 类适配器 Target 目标角色该角色定义把其他类转换为何种接口也就是我们的期望接口Adaptee 源角色你想把谁转换成目标角色这个谁就是源角色它是已经存在的、运行良好的类或对象经过适配器角色的包装它会成为一个崭新、靓丽的角色Adapter 适配器角色适配器模式的核心角色其他两个角色都是已经存在的角色而适配器角色是需要新建立的它的职责非常简单把源角色转换为目标角色怎么转换通过继承或是类关联的方式 对象适配器 类适配器是类间继承对象适配器是对象的合成关系也可以说是类的关联关系这是两者的根本区别实际项目中对象适配器使用到的场景相对比较多 使用场景 有动机修改一个已经投产中的接口时适配器模式可能是最合适的模式。但是请注意详细设计阶段不要考虑使用适配器模式使用主要场景为扩展应用中 鸭子和火鸡拥有两种不同的叫声鸭子的叫声调用quack方法而火鸡调用gobble方法。要求将火鸡的gobble方法适配成鸭子的quack方法从而让火鸡冒充鸭子 public interface Duck {void quack(); } public interface Turkey {void gobble(); } public class WildTurkey implements Turkey {Overridepublic void gobble() {System.out.println(gobble!);} } public class TurkeyAdapter implements Duck {Turkey turkey;public TurkeyAdapter(Turkey turkey) {this.turkey turkey;}Overridepublic void quack() {turkey.gobble();} } public class Client {public static void main(String[] args) {Turkey turkey new WildTurkey();Duck duck new TurkeyAdapter(turkey);duck.quack();} }桥接 Bridge将抽象与实现分离开来使他们可以独立变化 使用场景 不希望或不适用使用继承的场景接口或抽象类不稳定的场景重用性要求较高的场景 注意 发现类的继承有N层时可以考虑使用桥梁模式桥梁模式主要考虑如何拆分抽象和实现 Abstraction : 定义抽象类的接口Implementor 定义实现类的接口 RemoteControl表示遥控器指代Abstraction。TV表示电视指代Implementor。桥接模式将遥控器和电视分离开来从而可以独立改变遥控器或者电视的实现。 public abstract class TV {public abstract void on();public abstract void off();public abstract void tuneChannel(); } public class Sony extends TV {Overridepublic void on() {System.out.println(Sony.on());}Overridepublic void off() {System.out.println(Sony.off());}Override public void tuneChannel() {System.out.println(Sony.tuneChannel());} }组合 Composite 将对象组合成树形结构来表示整体/部分层次关系允许用户以相同的方式处理单独对象和组合对象。 组件类是组合类和叶子类的父类可以把组合类看成是树的中间节点。组合对象拥有一个或者多个组件对象因此组合对象的操作可以委托给组件对象去处理而组件对象可以是另一个组合对象或者叶子对象。Component 抽象构件角色 定义参加组合对象的共有方法和属性可以定义一些默认的行为或属性 Leaf 叶子构件 叶子对象其下再也没有其它的分支也就是遍历的最小单位 Composite 树枝构件 树枝对象它的作用是组合树枝节点和叶子节点形成一个树形结构 public class Composite extends Component { //构件容器private ArrayListComponent componentArrayList new ArrayListComponent();//增加一个叶子构件或树枝构件public void add(Component component) { this.componentArrayList.add(component);}//删除一个叶子构件或树枝构件public void remove(Component component) { this.componentArrayList.remove(component);}//获得分支下的所有叶子构件和树枝构件 publicArrayListComponent getChildren() {return this.componentArrayList;} } 使用场景 维护和展示部分-整体关系的场景如树形菜单、文件和文件夹管理从一个整体中能够独立出部分模块或功能的场景注意只要是树形结构就考虑使用组合模式 装饰 Decorator 动态地给一个对象添加一些额外的职责就增加功能来说装饰模式比生成子类更为灵活 Component 抽象构件 是一个接口或者是抽象类就是定义最核心的对象 Concrete Component 具体构件 Component 接口或抽象类的实现需要装饰的就是它 Decorator 装饰角色 一般是一个抽象类做什么用呢实现接口或者抽象方法它里面可不一定有抽象的方法在它的属性里必然有一个private变量指向Component抽象构件 Concrete Decorator 具体装饰角色 两个具体的装饰类要把最核心的、最原始的、最基本的东西装饰成其他东西 使用场景 需要扩展一个类的功能或给一个类增加附加功能需要动态给一个对象增加功能这些功能可以再动态地撤销需要为一批兄弟类进行改装或加装功能当然是首选装饰模式 装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component) 具体组件的方法实现不需要依赖于其他对象而装饰者组合了一个组件这样它可以装饰其他装饰者或者具体组件。所谓装饰就是把这个装饰者套在被装饰者之上从而动态扩展被装饰者的功能。装饰者的方法有一部分是自己的这属于它的功能然后调用被装饰者的方法实现从而也保留了被装饰者的功能。可以看到具体组件应当是装饰层次的最底层因为只有具体组件的方法实现不需要依赖于其他对象。 设计原则类应该对扩展开放对修改关闭。也就是添加新功能时不需要修改代码。饮料可以动态添加新的配料而不需要去修改饮料的代码。 门面 Facade 提供了一个统一的接口用来访问子系统中的一群接口从而让子系统更容易使用。 使用场景 为一个复杂的模块或子系统提供一个供外界访问的接口子系统相对独立外界对子系统的访问只要黑箱操作即可预防低水平人员带来的风险扩散 注意 一个子系统可以有多个门面门面不参与子系统内的业务逻辑 设计原则只和你的密友谈话也就是说客户对象所需要交互的对象应当尽可能的少。 享元 Flyweight 利用共享的方式来支持大量细粒度的对象这些对象一部分内部状态是相同的。 对象的信息分为两个部分内部状态和外部状态 内部状态 对象可共享出来的信息存储在享元对象内部并且不会随环境改变而改变 外部状态 对象得以依赖的一个标记是随环境改变而改变的、不可以共享的状态 使用场景 系统中存在大量的相似对象细粒度的对象都具备较接近的外部状态而且内部状态与环境无关也就是说对象没有特定身份需要缓冲池的场景 注意 享元模式是线程不安全的只有依靠经验在需要的地方考虑一下线程安全在大部分场景下不用考虑。对象池中的享元对象尽量多多到足够满足为止性能安全外部状态最好以java的基本类型作为标志如 String、int可以提高效率 Flyweight : 享元对象该角色需要注意的是内部状态处理应该与环境无关不应该出现一个操作改变了内部状态同时修改了外部状态这是绝对不允许的IntrinsicState : 内部状态享元对象共享内部状态ExtrinsicState : 外部状态每个享元对象的外部状态不同 public class FlyweightFactory {//定义一个池容器private static HashMapString,Flyweight pool new HashMapString,Flyweight();//享元工厂public static Flyweight getFlyweight(String Extrinsic){ //需要返回的对象Flyweight flyweight null;//在池中没有该对象if( pool.containsKey(Extrinsic) ) {flyweight pool.get(Extrinsic);} else {//根据外部状态创建享元对象flyweight new ConcreteFlyweight1(Extrinsic);//放置到池中pool.put(Extrinsic, flyweight);}return flyweight;} }代理 Proxy : 为其他对象提供一种代理以控制对这个对象的访问 Subject 抽象主题角色 抽象主题类可以是抽象类也可以是接口是一个最普通的业务类型定义无特殊要求 RealSubject 具体主题角色 也叫被委托角色、被代理角色是业务逻辑的具体执行者 Proxy 代理主题角色 也叫委托类、代理类。它负责对真实角色的应用把所有抽象主题类定义的方法限制委托给真实主题角色实现并且在真实主题角色处理完毕前后做预处理和善后处理工作 普通代理 就是我们要知道代理的存在然后才能访问调用者只知道代理而不用知道真实角色是谁屏蔽了真实角色的变更对高层模块的影响真实的主题角色想怎么修改就怎么修改对高层次的模块没有任何的影响只要你实现了接口所对应的方法该模式非常适合对扩展性要求较高的场合 强制代理 则是调用者直接调用真实角色而不用关心代理是否存在其代理的产生是由真实角色决定的这个概念就是要从真实角色查找到代理角色不允许直接访问真实角色。高层模块只要调用getProxy就可以访问真实角色的所有方法它根本不需要产生一个代理出来代理的管理已经由真实角色自己完成 动态代理 根据被代理的接口生成所有的方法也就是说给定一个接口动态代理会宣称我已经实现该接口下的所有方法了两条独立发展的线路。动态代理实现代理的职责业务逻辑Subject实现相关的逻辑功能两者之间没有必然的相互耦合的关系。通知Advice从另一个切面切入最终在高层模块也就是Client进行耦合完成逻辑的封装任务调用过程 动态代理的意图横切面编程在不改变我们已有代码结构的情况下增强或控制对象的行为首要条件被代理的类必须要实现一个接口 设计原则 单一责任原则 修改一个类的原因应该只有一个 换句话说就是让一个类只负责一件事当这个类需要做过多事情时就需要分解这个类。如果一个类承担的指责过多就等于把这些职责耦合在一起一个职责的变化可能会削弱这个类完成其他职责的能力。 开放封闭原则 类应该对扩展开放对修改关闭 扩展就是添加新功能的意思因此该原则要求在添加新功能时不需要修改代码。符合开闭原则最典型的设计模式就是装饰者模式它可以动态地将责任附加到对象上而不用去修改类的代码。 里氏替换原则 子类对象必须能够替换掉所有父类对象 继承是一种IS-A关系子类需要能够当成父类来使用并且需要比父类更特殊。如果不满足这个原则那么各个子类的行为上就会有很大差异增加继承体系的复杂度。 接口分离原则 不应该强迫客户依赖于它们不用的方法 因此使用多个专门的接口比使用单一的总接口要好 依赖倒置原则 高层模块不应该依赖于底层模块二者都应该依赖于抽象抽象不应该依赖于细节细节应该依赖于抽象。 高层模块包含一个应用程序中重要的策略选择和业务模块如果高层模块依赖于底层模块那么底层模块的改动就会直接影响到高层模块从而迫使高层模块也需要改动。 依赖于抽象意味着 任何变量都不应该有一个指向具体类的指针或者引用任何类都不应该从具体类派生任何方法都不应该覆写它的任何基类中的已经实现的方法 迪米特法则 LKP最少知识原则一个对象应当对其他对象有尽可能少的了解不和陌生人说话。 合成复用原则 尽量使用对象组合而不是通过继承来达到复用的目的 共同封闭原则 一起修改的类应该组合在一起(同一个包里)。如果必须修改应用程序的代码我们希望所有的修改都发生在一个包里(修改关闭)而不是遍布在很多包里。 稳定抽象原则 最稳定的包应该是最抽象的包不稳定的包应该是具体的包即包的抽象程度跟他的稳定性成正比 稳定依赖原则 包之间的依赖关系都应该是稳定方向依赖的包要依赖的包要比自己更具有稳定性 的主题角色想怎么修改就怎么修改对高层次的模块没有任何的影响只要你实现了接口所对应的方法该模式非常适合对扩展性要求较高的场合 强制代理 则是调用者直接调用真实角色而不用关心代理是否存在其代理的产生是由真实角色决定的这个概念就是要从真实角色查找到代理角色不允许直接访问真实角色。高层模块只要调用getProxy就可以访问真实角色的所有方法它根本不需要产生一个代理出来代理的管理已经由真实角色自己完成 动态代理 根据被代理的接口生成所有的方法也就是说给定一个接口动态代理会宣称我已经实现该接口下的所有方法了两条独立发展的线路。动态代理实现代理的职责业务逻辑Subject实现相关的逻辑功能两者之间没有必然的相互耦合的关系。通知Advice从另一个切面切入最终在高层模块也就是Client进行耦合完成逻辑的封装任务调用过程 动态代理的意图横切面编程在不改变我们已有代码结构的情况下增强或控制对象的行为首要条件被代理的类必须要实现一个接口 设计原则 单一责任原则 修改一个类的原因应该只有一个 换句话说就是让一个类只负责一件事当这个类需要做过多事情时就需要分解这个类。如果一个类承担的指责过多就等于把这些职责耦合在一起一个职责的变化可能会削弱这个类完成其他职责的能力。 开放封闭原则 类应该对扩展开放对修改关闭 扩展就是添加新功能的意思因此该原则要求在添加新功能时不需要修改代码。符合开闭原则最典型的设计模式就是装饰者模式它可以动态地将责任附加到对象上而不用去修改类的代码。 里氏替换原则 子类对象必须能够替换掉所有父类对象 继承是一种IS-A关系子类需要能够当成父类来使用并且需要比父类更特殊。如果不满足这个原则那么各个子类的行为上就会有很大差异增加继承体系的复杂度。 接口分离原则 不应该强迫客户依赖于它们不用的方法 因此使用多个专门的接口比使用单一的总接口要好 依赖倒置原则 高层模块不应该依赖于底层模块二者都应该依赖于抽象抽象不应该依赖于细节细节应该依赖于抽象。 高层模块包含一个应用程序中重要的策略选择和业务模块如果高层模块依赖于底层模块那么底层模块的改动就会直接影响到高层模块从而迫使高层模块也需要改动。 依赖于抽象意味着 任何变量都不应该有一个指向具体类的指针或者引用任何类都不应该从具体类派生任何方法都不应该覆写它的任何基类中的已经实现的方法 迪米特法则 LKP最少知识原则一个对象应当对其他对象有尽可能少的了解不和陌生人说话。 合成复用原则 尽量使用对象组合而不是通过继承来达到复用的目的 共同封闭原则 一起修改的类应该组合在一起(同一个包里)。如果必须修改应用程序的代码我们希望所有的修改都发生在一个包里(修改关闭)而不是遍布在很多包里。 稳定抽象原则 最稳定的包应该是最抽象的包不稳定的包应该是具体的包即包的抽象程度跟他的稳定性成正比 稳定依赖原则 包之间的依赖关系都应该是稳定方向依赖的包要依赖的包要比自己更具有稳定性

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

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

相关文章

宁波市建设工程检测协会网站手机网站建设市场

题目 表:Movies 表:Users 请你编写一个解决方案: 查找评论电影数量最多的用户名。如果出现平局,返回字典序较小的用户名。查找在 February 2020 平均评分最高 的电影名称。如果出现平局,返回字典序较小的电影名称。 …

联通网站备案系统网站策划建设方案书

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

个人网站设计及实现论文中国哪里正在大开发大建设

来源:工业机器人随着工业4.0时代的到来,机器视觉在智能制造业领域的作用越来越重要,为了能让更多用户获取机器视觉的相关基础知识,包括机器视觉技术是如何工作的、它为什么是实现流程自动化和质量改进的正确选择等。小编为你准备了…

极简资讯网站开发郑州网站建设的公司哪家好

简介: 东京奥运会已落下帷幕。比赛期间,全球亿万观众蜂拥至各大转播平台观看奥运赛事,平台直播能力显的尤为重要。阿里云作为视频直播平台的技术提供商,凭借在产品技术、资源带宽、服务保障等方面优势,可为各大转播平台…

江西省建设监督网站河南省建设厅建筑业信息网官网

聚类与判别分析概述 基本概念 聚类分析 聚类分析的基本思想是找出一些能够度量样本或指标之间相似程度的统计量,以这些统计量为划分类型的依据,把一些相似程度较大的样本(或指标)聚合为一类,把另外一些彼此之间相似程…

做网站宝安网站开发流程的三个部分

Linux set命令介绍 set命令是Linux操作系统中的内置shell命令,用于设置和取消shell变量和选项。它常用于shell脚本中,以配置环境并控制脚本的行为。 Linux set命令适用的Linux版本 set命令在所有主流的Linux发行版中都可以使用,包括但不限…

expedia电子商务网站建设个人网站设计案例

简介 这是一个轻量级、高性能的基于 Netty 的 WebSocket 框架,提升你的 WebSocket 开发体验,为 Spring Boot 带来全新的 WebSocket 功能。 该项目使你可以轻松集成 WebSocket 到你的 Spring Boot 项目中,提供了 Tomcat WebSocket 的简单性&a…

周口在线网站建设往网站上做新东西需要什么

欢迎来到本篇详细解释 MVC(Model-View-Controller)设计模式的教程。MVC 是一种用于组织应用程序的设计模式,有助于将应用程序分成不同的部分,以提高代码的可维护性和可扩展性。在本文中,我们将深入研究 MVC 模式&#…

led灯网站建设案例绍兴做企业网站的公司

博主介绍:✌全网粉丝4W,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验…

军队信息化建设网站wordpress运行

一.ListView简介 在Android开发中&#xff0c;ListView是一个比较常用的控件。它以列表的形式 展示具体数据内容&#xff0c;并且能够根据数据的长度自适应屏幕显示。 二.ListView简单用法 代码部分 1.布局界面 activity_main.xml 代码&#xff1a; <?xml version"…

企业网站建设方案书前言wordpress苗木模板

前面给大家将了一下slurm集群的简单配置&#xff0c;这里给大家再提升一下&#xff0c;配置slurm服务的restful的api&#xff0c;这样大家可以将slurm服务通过api整合到桌面或者网页端&#xff0c;通过桌面或者网页界面进行管理。 1、SLURM集群配置 这里请大家参考&#xff1…

中学加强校园网站建设输入代码即可玩的小游戏

一、TCP多进程并发 1.地址快速重用 先退出服务端&#xff0c;后退出客户端&#xff0c;则服务端会出现以下错误&#xff1a; 地址仍在使用中 解决方法&#xff1a; /*地址快速重用*/ int flag1,len sizeof (int); if ( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &a…

新开传奇网站大全江苏省国家示范校建设专题网站

分类目录&#xff1a;《深入理解强化学习》总目录 在文章《深入理解强化学习——马尔可夫决策过程&#xff1a;蒙特卡洛方法-[基础知识]》中我们介绍了利用蒙特卡洛方法计算马尔可夫决策过程价值的方法&#xff0c;本文将用代码定义一个采样函数。采样函数需要遵守状态转移矩阵…

兖州建设公司网站wordpress中文破解主题

文章目录 CentOS7安装部署MySQL80一、前言二、正文1.安装部署1&#xff09;卸载 mariadb2&#xff09;MySQL安装3&#xff09;启动4&#xff09;首次登录 2.允许所有主机连接3.修改密码4.my.cnf配置文件5.开启binlog6.密码校验策略7.密码过期8.表名大小写敏感9.最大连接数10.导…

网站备案期间怎么做外贸销售管理制度

进程是一个其中运行着一个或多个线程的地址空间和这些线程所需要的系统资源。一般来说&#xff0c;Linux系统会在进程之间共享程序代码和系统函数库&#xff0c;所以在任何时刻内存中都只有代码的一份拷贝。 1&#xff0c;ps命令 作用&#xff1a;ps命令主要用于查看系统中进程…

做网站标志有限颜色使用的吗北京通州住房和城乡建设部网站

目录 TSDF的基本原理 SLAM中TSDF建图的实现 TSDF的基本原理 TSDF建图&#xff0c;即使用截断符号距离函数&#xff08;Truncated Signed Distance Function&#xff09;的建图方法&#xff0c;是一种用于3D重建和机器人导航的技术。TSDF利用所谓的“截断有符号距离函数”来构…

android 网站开发夜深人不静免费看高清

实验室要求统一Linux版本&#xff0c;原来我用的是Ubuntu&#xff0c;现在我在的实验室是centos&#xff0c;我也就只能改了。实验室和个人不同&#xff0c;个人的Linux版本可能经常换&#xff0c;只要有新的版本出来&#xff0c;我就会去下载下来&#xff0c;在虚拟机里面试一…

安徽合肥网站制作苏州 网站建设 app

黑马程序员前端web入门&#xff1a;新浪新闻 几点学习到的&#xff1a; 设置li无圆点: list-style: none;设置a无下划线&#xff1a;text-decoration: none;a属于行内元素&#xff0c;高度hegiht不起作用&#xff0c;可以设置 display: block; 把它变成块元素。此时&#xff0c…

哈尔滨专业网站制作设计珠海市网站开发公司电话

QT线程的使用 循环中程序的等待 先看效果1 pro文件2 头文件3 源文件4 ui文件先看效果 1 pro文件 QT += concurrent2 头文件 #ifndef MAINWINDOW_H #define MAINWINDOW_H

怎么用个人电脑做网站临沂做公司网站

问题描述&#xff1a; 内存泄漏积累过多最终会导致内存溢出&#xff0c;当内存占用过大&#xff0c;进程会被killed掉。 解决过程&#xff1a; 在代码的运行阶段输出内存占用量&#xff0c;观察在哪一块存在内存剧烈增加或者显存异常变化的情况。但是在这个过程中要分级确认…