常用设计模式—

一、设计模式简介

23种设计模式

1.1、设计模式七大原则

1.开闭原则 
对扩展开放,对修改关闭。

2.依赖倒置原则(面向接口编程)
依赖关系通过接口、抽象类。

3.单一职责原则 
一个类、接口、方法只负责一项职责或职能。

4.接口隔离原则 
客户端不需要多余的接口,一个类对另一个类的依赖建立在最小的接口上。

5.迪米特法则(最少知道原则)
一个对象对其他对象尽可能少的了解,每个类尽量减少对其他类的依赖(降低耦合)。

6.里氏替换原则
1.子类必须实现父类的抽象方法,但不得重写(覆盖)父类的非抽象(已实现)方法。
2.子类中可以增加自己特有的方法。
3.子类实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
4.子类实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

7.合成/复用原则(组合/复用原则)
尽量使用合成/聚合,少用继承。

1.2、设计模式种类 

1.2.1、创建型模式5种 

提供实例化的方法,为适合的状况提供相应的对象创建方法。
    工厂方法模式【Factory Method】
    抽象工厂模式【Abstract Factory】
    创建者模式【Builder】
    原型模式【Prototype】
    单例模式【Singleton】

1.2.2、结构型模式7种 

用来处理实体之间的关系,使得这些实体能够更好地协同工作。
    外观模式【Facade】
    适配器模式【Adapter】
    代理模式【Proxy】
    装饰模式【Decorator】
    桥接模式【Bridge】
    组合模式【Composite】
    享元模式【Flyweight】

1.2.3、行为型模式11种  

不同的实体间进行通信,为实体之间的通信提供更容易,更灵活的通信方法。
    模板方法模式【Template Method】
    观察者模式【Observer】
    状态模式【State】
    策略模式【Strategy】
    职责链模式【Chain of Responsibility】
    命令模式【Command】
    访问者模式【Visitor】
    调停者模式【Mediator】
    备忘录模式【Memento】
    迭代器模式【Iterator】
    解释器模式【Interpreter】

二、常用的设计模式 

2.1、工厂模式 

将抽象类的子类建造控制在工厂中,只关注产品的生产,便于管理。

组成 
IProduct:抽象产品接口,描述所有实例所共有的公共接⼝。
Product:具体产品类,实现抽象产品类的接⼝,⼯⼚ 类创建对象,有多个需要定义多个。
IFactory:抽象⼯⼚接口,描述具体⼯⼚的公共接⼝。
Factory:具体⼯⼚类,实现创建产品类对象,实现抽象⼯⼚类的接⼝,有多个需要定义多个。

public interface Meat {String getName();
}public class BeefMeat implements Meat{public String getName(){return "牛肉";}
}public class PigMeat implements Meat{public String getName(){return "猪肉";}
}public class MeatFactory {public static Meat creatMeat(String meatName){if("Pig".equals(meatName)){return new PigMeat();}if ("Beef".equals(meatName)){return new BeefMeat();}else {return null;}}
}public static void main(String[] args) {Meat meat = MeatFactory.creatMeat("Beef");System.out.println(meat.getName());
}

2.2、单例模式 


//静态内部类单例
public class Singleton {private static class LazyHolder {private static final Singleton single = new Singleton();} private Singleton (){}public static final Singleton getSingle() {return LazyHolder.single;}
}//枚举
enum Singleton {INSTANCE; //属性public void sayOK() {System.out.println("ok~");}
}

2.3、建造者模式 

常用于一些基本部件不变而组合方式常变的场景,关注产品的组合方式和装配顺序。

组成 

Product(产品):具体的产品对象。
Builder(抽象建造者):创建 Product 对象的各个部件指定的接口或抽象类。
ConcreteBuilder(具体建造者):实现Builder 接口,构建和装配各个部件。
Director(指挥者):隔离客户与对象的产生过程,负责控制产品对象的生产过程。

// 产品
public class Computer {private String cpu;private String memory;private String disk;public String getCpu() {return cpu;}public void setCpu(String cpu) {this.cpu = cpu;}public String getMemory() {return memory;}public void setMemory(String memory) {this.memory = memory;}public String getDisk() {return disk;}public void setDisk(String disk) {this.disk = disk;}@Overridepublic String toString() {return "Computer{" +"cpu='" + cpu + '\'' +", memory='" + memory + '\'' +", disk='" + disk + '\'' +'}';}
}// 抽象建造者
public interface ComputerBuilder {void buildCpu();void buildMemory();void buildDisk();Computer buildComputer();
}// 具体建造者
public class ComputerConcreteBuilder implements ComputerBuilder{Computer computer;public ComputerConcreteBuilder() {computer = new Computer();}@Overridepublic void buildCpu() {System.out.println("建造 8核 CPU");computer.setCpu("8核");}@Overridepublic void buildMemory() {System.out.println("建造 32G 主存");computer.setMemory("32G");}@Overridepublic void buildDisk() {System.out.println("建造 1TG 硬盘");computer.setDisk("1TG");}@Overridepublic Computer buildComputer() {return computer;}
}// 指挥者
public class ComputerDirector {public Computer constructComputer(ComputerBuilder computerBuilder){computerBuilder.buildCpu();computerBuilder.buildMemory();computerBuilder.buildDisk();return computerBuilder.buildComputer();}
}public static void main(String[] args) {ComputerDirector computerDirector = new ComputerDirector();ComputerBuilder computerBuilder = new ComputerConcreteBuilder();Computer computer = computerDirector.constructComputer(computerBuilder);System.out.println(computer);
}

2.4、适配器模式 

角色 
Source:待适配的类、  Targetable:适配器、  Adapter:目标接口

类适配器、对象适配器、接口适配器

/*** 目标接口*/
public interface Targetable {void editFile();void addFile();
}/*** 待适配类*/
public class Source {public void editFile(){System.out.println("待适配类---Source---editFile---");}
}/*** 类适配器*/
public class Adapater extends Source implements Targetable{@Overridepublic void addFile() {System.out.println("类适配器---Adapater---addFile");}public static void main(String[]args){Targetable targetable = new Adapater();targetable.addFile();targetable.editFile();}
}/*** 对象适配器*/
public class ObjectAdapter implements Targetable{private Source source;public ObjectAdapter(Source sou){super();this.source = sou;}@Overridepublic void editFile() {//System.out.println("对象适配器---ObjectAdapter---editFile");this.source.editFile();}@Overridepublic void addFile() {System.out.println("对象适配器---ObjectAdapter---addFile");}public static void main(String[]args){Source so = new Source();Targetable targetable = new ObjectAdapter(so);targetable.addFile();targetable.editFile();}
}/*** 接口类适配器*/
public abstract class AbstractAdapter implements Targetable{@Overridepublic void editFile() {}@Overridepublic void addFile() {}
}public class SourceSub1 extends AbstractAdapter{@Overridepublic void editFile() {System.out.println("SourceSub1---editFile");}
}public class SourceSub2 extends AbstractAdapter{@Overridepublic void addFile() {System.out.println("SourceSub2---addFile");}
}

2.5、外观模式

角色
子系统角色:实现子系统功能。
门面角色:熟悉个子系统功能和调用关系,根据客户需要封装成统一方法对外提供服务。
客户角色:通过门面实现需求。

public class Model01 {public void model01Start(){System.out.println("Model01---model01Start");}public void model01Shutdown(){System.out.println("Model01---model01Shutdown");}
}public class Model02 {public void model02Start(){System.out.println("Model02---model02Start");}public void model02Shutdown(){System.out.println("Model02---model02Shutdown");}
}public class Facade {private Model01 model01;private Model02 model02;public Facade(){this.model01 = new Model01();this.model02 = new Model02();}public void start(){this.model01.model01Start();this.model02.model02Start();}public void shutdown(){this.model01.model01Shutdown();this.model02.model02Shutdown();}public static void main(String arg[] ) {Facade facade = new Facade();facade.start();facade.shutdown();}
}

2.6、桥接模式

使用桥梁(组合方式)将两个抽象类连起来,
将抽象与实现分离,解决需求多变继承类过多问题。
如: 开发跨平台的视频播放器,平台有 Android、iOS、Windows、Linux、Mac,
播放器的格式有 MP4、RMVB、FLV 格式。这种情况下,适合使用桥接模式。

public interface Driver {void executeSQL();
}public class MysqlDriver implements Driver{@Overridepublic void executeSQL() {System.out.println("MysqlDriver---executeSQL");}
}public class OracleDriver implements Driver{@Overridepublic void executeSQL() {System.out.println("OracleDriver---executeSQL");}
}public abstract class DriverManagerBridge {private Driver driver;public Driver getDriver() {return driver;}public void setDriver(Driver driver) {this.driver = driver;}public void executeSql(){this.driver.executeSQL();}
}public class MyDriverBridge extends DriverManagerBridge{public void execute(){getDriver().executeSQL();}public static void main(String arg[] ) {DriverManagerBridge driverManagerBridge = new MyDriverBridge();driverManagerBridge.setDriver(new MysqlDriver());driverManagerBridge.executeSql();driverManagerBridge.setDriver(new OracleDriver());driverManagerBridge.executeSql();}
}

2.7、享元模式 

通过对象的复用减少对象的创建次数和数量。

public class Memory {private int size; // 内存大小private boolean isused; // 内存是否使用private String id; // 内存IDpublic Memory(int size, boolean isused, String id) {this.size = size;this.isused = isused;this.id = id;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public boolean isIsused() {return isused;}public void setIsused(boolean isused) {this.isused = isused;}public String getId() {return id;}public void setId(String id) {this.id = id;}
}import java.util.ArrayList;
import java.util.List;
import java.util.UUID;public class MemoryFactory {private static List<Memory> memoryList = new ArrayList<>();// 获取内存public static Memory getMemory(int size){Memory memory = null;for (int i=0;i< memory.getSize();i++){memory = memoryList.get(i);if(memory.isIsused()==false&&memory.getSize()==size){memory.setIsused(true);memoryList.set(i,memory);break;}}if(memory==null){memory = new Memory(32,true, UUID.randomUUID().toString());memoryList.add(memory);}return memory;}// 释放内存public static void releaseMemory(String id){for (int i=0;i<memoryList.size();i++){Memory memory = memoryList.get(i);if(memory.getId().equals(id)){memory.setIsused(false);memoryList.set(i,memory);break;}}}
}

2.8、策略模式 

通过多态消除 if else

public interface Car {void run();
}public class BMWCar implements Car {public void run() {System.out.println("宝马车在行驶......");}
}public class BMWCar implements Car {public void run() {System.out.println("宝马车在行驶......");}
}public class CarContext {private static CarContext carContext = new CarContext();private CarContext(){}private static Map carMap = new HashMap(16);static {carMap.put("BMWCar",new BMWCar());carMap.put("BenzCar",new BenzCar());}public Car create(Integer payCode){return (Car) carMap.get(payCode);}public static CarContext getInstance(){return carContext;}
}

2.9、模版方法模式 

将相同部分代码,放在抽象的父类中;不同的代码,放在不同的子类中。符合开闭原则。

/*** 抽象的父类 */
public abstract class Fridge {/*** 模板方法 不能被修改,用 final 修饰*/protected final void store() {openDoor();closeDoor();// 这个钩子方法可以让子类控制模板方法的执行流程if (needColdStorage()) {codeStorage();}put();}/*** 该方法是不变的,不允许子类修改*/final void openDoor() {System.out.println("打开冰箱门");}/*** 该方法是不变的,不允许子类修改*/final void codeStorage() {System.out.println("打开冷藏功能");}/*** 钩子方法 , 子类可以进行覆盖 将适当的权限开放给应用层,用于控制模板方法流程。*/protected boolean needColdStorage() {return false;}/*** 抽象方法 , 需要子类进行实现*/abstract void put();final void closeDoor() {System.out.println("关闭冰箱门");}
}/*** 鱼放冰箱*/
public class FishFridge extends Fridge {@Overridevoid put() {System.out.println("把鱼放进冰箱");}@Overrideprotected boolean needColdStorage() {// 需要冷藏存储return true;}
}/*** 大象放冰箱*/
public class ElephantFridge extends Fridge {@Overridevoid put() {System.out.println("把大象放进冰箱");}
}public static void main(String[] args) {// 把大象放到冰箱Fridge elephantFridge = new ElephantFridge();elephantFridge.store();System.out.println();// 把鱼放到冰箱Fridge fishFridge = new FishFridge();fishFridge.store();}

2.10、观察者模式 

将观察对象封装进  private Vector<Observer> obs; 队列中,被观察的内容改变时遍历队列,通知到观察者。

/*** 被观察的对象* JDK 提供了对观察者模式的支持 , 被观察者可以继承 Observable 类*/
public class Game extends Observable {private String name;public Game(String name) {this.name = name;}public String getName() {return name;}/*** 用户提交问题*/public void produceQuestion(Game game, String question) {System.out.println(" 在 " + game.name + " 游戏中提交问题 : " + question);// 代表 被观察者 的状态发生了改变setChanged();// 通知 观察者notifyObservers(question);}
}/*** 观察者 — 管理员类*/
public class Manager implements Observer {/*** 管理员名称*/private String name;public Manager(String name) {this.name = name;}@Overridepublic void update(Observable o, Object arg) {// 获取 被观察者 对象Game game = (Game) o;// 获取 被观察者 对象 调用 notifyObservers 方法的参数String question = (String) arg;System.out.println(name + " 观察者 接收到 被观察者 " + game.getName() + " 的通知 , 用户 " + " 提出问题 " + question);}
}public static void main(String[] args) {// 创建被观察者Game game = new Game("Cat And Mouse");// 创建观察者Manager manager = new Manager("Tom");// 关联 观察者 与 被观察者game.addObserver(manager);// 在游戏中提交问题game.produceQuestion(game,"游戏崩溃");}

2.11、责任链模式 

责任两两关联,将被处理体传递到下个责任人。
一个请求的处理,需要多个对象协作进行处理。
OA的审批流程、账号注册时的阶段校验等。

/*** 用户账户信息  账号 , 密码 , 电话号码*/
public class UserAccount {private String userName;private String password;private String phoneNumber;public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getPhoneNumber() {return phoneNumber;}public void setPhoneNumber(String phoneNumber) {this.phoneNumber = phoneNumber;}
}/*** 校验类的父类 校验账号,校验密码,校验手机号 的请求类都需要继承该类*/
public abstract class Verify {// 下个校验器protected Verify nextVerify;/*** 设置下一个校验器*/public void setNextVerify(Verify verify) {this.nextVerify = verify;}/*** 校验过程*/public abstract void deploy(UserAccount userAccount);
}/*** 校验用户名称*/
public class UserNameVerify extends Verify{@Overridepublic void deploy(UserAccount userAccount) {if (userAccount.getUserName() != null){System.out.println("用户名校验通过");// 获取下一个验证器if (nextVerify != null) {nextVerify.deploy(userAccount);}} else {System.out.println("用户名校验未通过");}}
}/*** 校验密码*/
public class PasswordVerify extends Verify{@Overridepublic void deploy(UserAccount userAccount) {if (userAccount.getPassword() != null){System.out.println("密码校验通过");// 获取下一个验证器if (nextVerify != null) {nextVerify.deploy(userAccount);}} else {System.out.println("密码校验未通过");}}
}/*** 校验手机号*/
public class PhoneVerify extends Verify{@Overridepublic void deploy(UserAccount userAccount) {if (userAccount.getPhoneNumber() != null){System.out.println("手机号校验通过");// 获取下一个验证器if (nextVerify != null) {nextVerify.deploy(userAccount);}} else {System.out.println("手机号校验未通过");}}
}public static void main(String[] args) {UserNameVerify userNameVerify = new UserNameVerify();PasswordVerify passwordVerify = new PasswordVerify();PhoneVerify phoneVerify = new PhoneVerify();UserAccount userAccount = new UserAccount();userAccount.setUserName("username");userAccount.setPassword("123456");userAccount.setPhoneNumber("13888888888");// 创建职责链userNameVerify.setNextVerify(passwordVerify);passwordVerify.setNextVerify(phoneVerify);// 开始校验,执行职责链。userNameVerify.deploy(userAccount);}

2.12、状态模式

一个对象,存在多个状态,状态可以相互转换;内部状态改变,行为也要进行改变。
将各种状态的转换逻辑,分到状态的子类中,减少相互依赖。可用享元模式,在多个上下文中,共享状态实例。

/*** 视频状态 父类*/
public abstract class VedioState {/*** 视频播放上下文 声明为 protected , 子类可以拿到该成员变量*/protected VedioContext vedioContext;public void setVedioContext(VedioContext vedioContext) {this.vedioContext = vedioContext;}/*** 播放 对应播放状态*/public abstract void play();/*** 停止 对应停止状态*/public abstract void pause();/*** 快进 对应快进状态*/public abstract void speed();/*** 停止 对应停止状态*/public abstract void stop();
}/*** 视频的播放状态 可以进行 快进 , 暂停 , 停止 操作*/
public class PlayState extends VedioState{@Overridepublic void play() {System.out.println("正常播放视频");}@Overridepublic void pause() {super.vedioContext.setVedioState(VedioContext.PAUSE_STATE);}@Overridepublic void speed() {super.vedioContext.setVedioState(VedioContext.SPEED_STATE);}@Overridepublic void stop() {super.vedioContext.setVedioState(VedioContext.STOP_STATE);}
}/*** 视频快进状态  可 播放、暂停、停止*/
public class SpeedState extends VedioState{@Overridepublic void play() {super.vedioContext.setVedioState(VedioContext.PLAY_STATE);}@Overridepublic void pause() {System.out.println("快进播放视频");}@Overridepublic void speed() {super.vedioContext.setVedioState(VedioContext.SPEED_STATE);}@Overridepublic void stop() {super.vedioContext.setVedioState(VedioContext.STOP_STATE);}
}/*** 暂停状态  可切换到 播放、快进、停止*/
public class PauseState extends VedioState{/*** 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可*/@Overridepublic void play() {super.vedioContext.setVedioState(VedioContext.PLAY_STATE);}/*** 暂停时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 暂停 的状态即可*/@Overridepublic void pause() {System.out.println("暂停播放视频");}/*** 快进时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 快进 的状态即可*/@Overridepublic void speed() {super.vedioContext.setVedioState(VedioContext.SPEED_STATE);}/*** 停止时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 停止 的状态即可*/@Overridepublic void stop() {super.vedioContext.setVedioState(VedioContext.STOP_STATE);}
}/*** 视频的停止状态  能 播放;不能快进、暂停*/
public class StopState extends VedioState{/*** 播放时 , 只需要调用 PlayState 父类 VedioState 的上下文 VedioContext*      将上下文 VedioContext 中的状态 , 设置为 播放 的状态即可*/@Overridepublic void play() {super.vedioContext.setVedioState(VedioContext.PLAY_STATE);}/*** 不能暂停*/@Overridepublic void pause() {System.out.println("停止状态不能暂停");}/*** 不能快进*/@Overridepublic void speed() {System.out.println("停止状态不能快进");}@Overridepublic void stop() {System.out.println("停止播放视频");}
}/*** 享元模式 共享同一个对象*/
public class VedioContext {// 当前的状态private VedioState mVedioState;// 播放状态public final static PlayState PLAY_STATE = new PlayState();// 暂停状态public final static PauseState PAUSE_STATE = new PauseState();// 快进状态public final static SpeedState SPEED_STATE = new SpeedState();// 停止状态public final static StopState STOP_STATE = new StopState();public VedioState getVedioState() {return mVedioState;}public void setVedioState(VedioState mVedioState) {this.mVedioState = mVedioState;this.mVedioState.setVedioContext(this);}public void play() {this.mVedioState.play();}public void pause() {this.mVedioState.pause();}public void speed() {this.mVedioState.speed();}public void stop() {this.mVedioState.stop();}
}public static void main(String[] args) {VedioContext vedioContext = new VedioContext();vedioContext.setVedioState(VedioContext.PLAY_STATE);System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.pause();System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.speed();System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.stop();System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());vedioContext.speed();System.out.println("当前视频状态 : " + vedioContext.getVedioState().getClass().getSimpleName());
}

2.13、备忘录模式 

存档信息:封装 存档信息。
恢复机制:为用户提供 可恢复 机制。
如: Ctrl + Z 执行 "撤销" 操作,游戏中的存档使用。

/*** 文档 要保存的对象*/
public class Article {private String title;private String content;public Article(String tittle, String content) {this.title = tittle;this.content = content;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}/*** 保存信息到备忘录*/public ArticleMemento saveToMemento() {ArticleMemento articleMemento = new ArticleMemento(title, content);return articleMemento;}/*** 从备忘录恢复*/public void undoFromMemento(ArticleMemento articleMemento) {this.title = articleMemento.getTitle();this.content = articleMemento.getContent();}@Overridepublic String toString() {return "Article{" +"title='" + title + '\'' +", content='" + content + '\'' +'}';}
}/*** 文档的备忘录类*/
public class ArticleMemento {private String title;private String content;public ArticleMemento(String title, String content) {this.title = title;this.content = content;}public String getTitle() {return title;}public String getContent() {return content;}@Overridepublic String toString() {return "ArticleMemento{" +"title='" + title + '\'' +", content='" + content + '\'' +'}';}
}/*** 备忘录管理类*/
public class ArticleMementoManager {/*** 存储所有的备忘录信息 在 栈 数据结构中存储 , 特点后进先出*/private final Stack<ArticleMemento> mArticleMementoStack = new Stack<>();/*** 获取栈顶的备忘录信息*/public ArticleMemento getArticleMemento() {return mArticleMementoStack.pop();}/*** 备忘录信息入栈 放在栈顶*/public void setArticleMemento(ArticleMemento articleMemento) {mArticleMementoStack.push(articleMemento);}
}public static void main(String[] args) {ArticleMementoManager articleMementoManager = new ArticleMementoManager();// 创建并输入文档内容Article article = new Article("标题", "内容");// 保存备忘录信息ArticleMemento articleMemento = article.saveToMemento();// 将备忘录信息设置到 备忘录管理者articleMementoManager.setArticleMemento(articleMemento);// 打印备忘录内容System.out.println("文档信息 : " + article.toString());// 修改文档内容article.setTitle("标题 2");article.setContent("内容 2");// 保存新的备忘录信息articleMemento = article.saveToMemento();// 将备忘录信息设置到 备忘录管理者articleMementoManager.setArticleMemento(articleMemento);// 打印备忘录内容System.out.println("文档信息 : " + article.toString());// 此时 ArticleMementoManager 中存储了 2 个存档// 存档 1 : Article{title='标题', content='内容', image='图片链接'}// 存档 2 : Article{title='标题 2', content='内容 2', image='图片链接 2'}// 使用备忘录回退// 先将栈顶的当前备忘录出栈 , 移除articleMementoManager.getArticleMemento();// 然后获取上一个备忘录 , 并设置到 Article 中article.undoFromMemento(articleMementoManager.getArticleMemento());// 打印备忘录内容System.out.println("文档信息 : " + article.toString());}

2.14、命令模式 

命令模式可使 命令的 发送者 和 接收者 完全解耦,发送者与接收者靠命令交互,把命令执行的逻辑类封装在命令类里。
命令模式 与 备忘录模式:通过 备忘录模式 保存 命令模式 的 命令历史记录,可获之前的命令。

/*** 命令执行 — 逻辑类*/
public class Game {private String name;public Game(String name) {this.name = name;}public void open() {System.out.println(this.name + " 开放");}public void close() {System.out.println(this.name + " 关闭");}
}/*** 命令接口*/
public interface Command {/*** 执行命令方法*/void execute();
}/*** 开放命令*/
public class OpenCommand implements Command{private Game game;public OpenCommand(Game game) {this.game = game;}@Overridepublic void execute() {this.game.open();}
}/*** 关闭命令*/
public class CloseCommand implements Command {private Game game;public CloseCommand(Game game) {this.game = game;}@Overridepublic void execute() {this.game.close();}
}/*** 命令接收者*/
public class Manager {/*** 存放命令*/private ArrayList<Command> commands = new ArrayList<>();/*** 添加命令*/public void addCommand(Command command) {commands.add(command);}/*** 执行命令*/public void executeCommand() {for (Command command : commands) {// 逐个遍历执行命令command.execute();}// 命令执行完毕后 , 清空集合commands.clear();}
}public static void main(String[] args) {Game game01 = new Game("小游戏");Game game02 = new Game("大游戏");OpenCommand openCommand = new OpenCommand(game01);CloseCommand closeCommand = new CloseCommand(game02);// 发送命令Manager manager = new Manager();manager.addCommand(openCommand);manager.addCommand(closeCommand);// 执行命令manager.executeCommand();}

2.15、访问者模式 

2.16、调停者模式 

2.17、迭代器模式 

2.18、解释器模式 

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

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

相关文章

算法之排序

文章目录 前言一、二分查找1、正常二分2、二分找第一个出现要查找的数的位置3、在旋转数组中找最小数字二分总结 一、归并排序1、正常归并2、小和问题归并总结 前言 之前我们学习了各种排序算法&#xff0c;今天来让我们看看在线OJ上的题目吧&#xff0c;有哪些排序算法有什么…

CPP-Templates-2nd--第十四章 实例化

目录 14.1 On-Demand实例化 14.2 延迟实例化 14.2.1 部分实例化和完整实例化 14.2.2 实例化组件 14.3 C实例化模型 14.3.1 两阶段查找 14.3.2 POI 14.3.3 包含式模型 14.4 几种实现方案 14.4.1 贪婪实例化 14.4.2 查询实例化 14.4.3 迭代实例化 参考&#xff1a;…

jvm 内存模型介绍

一、类加载子系统 1、类加载的过程&#xff1a;装载、链接、初始化&#xff0c;其中&#xff0c;链接又分为验证、准备和解析 装载&#xff1a;加载class文件 验证&#xff1a;确保字节流中包含信息符合当前虚拟机要求 准备&#xff1a;分配内存&#xff0c;设置初始值 解析&a…

数据分析工具有哪些,哪个好学?

Tableau、帆软BI、思迈特BI、SpeedBI数据分析云……这些都是比较常见的BI数据分析工具。从学习成本、操作难度以及数据可视化分析效果来看&#xff0c;SpeedBI数据分析云都表现地可圈可点。 1、不需下载安装、学习成本低 SpeedBI数据分析云是一款SaaS BI数据分析工具&#xf…

【AIGC专题】Stable Diffusion 从入门到企业级实战0601

一、前言 本章是《Stable Diffusion 从入门到企业级实战》系列的第六部分Prompt专题篇《Stable Diffusion Prompt 专题》第01节 《Stable Diffusion Prompt 通用画风操作实战》。本部分内容&#xff0c;位于整个Stable Diffusion生态体系的位置如下图黄色部分所示&#xff1a;…

【简单教程】利用Net2FTP构建免费个人网盘,实现便捷的文件管理

文章目录 1.前言2. Net2FTP网站搭建2.1. Net2FTP下载和安装2.2. Net2FTP网页测试 3. cpolar内网穿透3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 文件传输可以说是互联网最主要的应用之一&#xff0c;特别是智能设备的大面积使用&#xff0c;无论是个人…

Python中异常处理4-4

在Python中的异常处理4-1_棉猴的博客-CSDN博客中提到&#xff0c;在try块中的代码运行时如果出现异常&#xff0c;会自动抛出这个异常。可以通过raise语句手动抛出异常。 1 raise语句手动抛出异常 raise后面跟要抛出的异常类或者异常类的实例&#xff0c;表示手动抛出该异常&…

翻牌闯关游戏

翻牌闯关游戏 3关&#xff1a;关卡由少至多12格、20格、30格图案&#xff1a;12个玩法&#xff1a;点击两张卡牌&#xff0c;图案一到即可消除掉 记忆时长(毫秒)&#xff1a;memoryDurationTime:5000 可配置&#xff0c;默认5000 提示游戏玩法&#xff1a;showTipsFlag:1 可…

【分布式】分布式ID

目录 前言一、雪花算法snowflake1. 组成2. 优缺点3. 时钟回拨怎么解决a. 时钟回拨b. 解决方案 4. 项目中如何使用 二、基于Redis三、基于Zookeeper四、号段模式五、指定步长的自增ID六、UUID参考 六、扩展总结 前言 分布式场景下&#xff0c;一张表可能分散到多个数据结点上。因…

uniapp——实现在线选座功能——技能提升

首先声明一点&#xff1a;下面的内容是从一个uniapp的程序中摘录的&#xff0c;并非本人所写&#xff0c;先做记录&#xff0c;以免后续遇到相似需求抓耳挠腮。 这里写目录标题 效果图代码——html部分cu-custom组件anil-seat组件 代码——jscss部分 效果图 代码——html部分 …

gin-基础笔记

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、get和post方法二、重定向总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;随着人工智能的不断发展&#xff0…

uniapp掉完接口后刷新当前页面方法

uniapp掉完接口后刷新当前页面方法 掉完接口&#xff0c;里面加下面这个方法uni.redirectTo({}) setTimeout(() > {uni.redirectTo({// 当前页面路由url: /pages/property/mutualrotation/mutualrotation);}, 500)实例 mutualRotationSubmit() {let self this;uni.showMod…

Python Opencv实践 - 视频文件操作

参考资料&#xff1a; 视频处理VideoCapture类---OpenCV-Python开发指南&#xff08;38&#xff09;_python opencv videocapture_李元静的博客-CSDN博客 OpenCV VideoCapture.get()参数详解 - 简书FOURCC四字符码对照表_4fvcc_Kellybook的博客-CSDN博客 import cv2 as cv im…

网络基础--1.网络纵横

网络的发展历程 计算机由原来的只能单一处理信息&#xff08;单用户批处理&#xff09;逐步发展为多用户批处理&#xff0c;可以实现一台计算机连接多个终端同时使用一台计算机&#xff08;分时系统&#xff09;&#xff0c;但是多个终端之间不能相互通信&#xff0c;再发展成为…

API接口文档管理系统平台搭建(更新,附系统源码及教程)

简介 这是一款简洁大方的API接口文档管理系统&#xff0c;附系统源码及教程方法。可以轻松管理和使用API接口。 安装步骤 打开config/database.php配置数据库信息导入数据库data.sql设置运行目录为/public伪静态设置think PHP后台地址/admin/login.html 账号&#xff1a;adm…

git 远程名称 远程分支 介绍

原文&#xff1a; 开发者社区> 越前君> 细读 Git | 让你弄懂 origin、HEAD、FETCH_HEAD 相关内容 读书笔记&#xff1a;担心大佬文章搬家&#xff0c;故整理此学习笔记 远程名称&#xff08;Remote Name&#xff09; Origin 1、 origin 只是远程仓库的一个名称&#xff…

【Kafka】Kafka再平衡机制及相关参数

背景 Kafka作为一款基于发布订阅模式的消息队列&#xff0c;生产者将消息发送到Kafka集群&#xff08;Brokers&#xff09;中&#xff0c;消费者&#xff08;Consumer Group &#xff09;拉取消息进行消费&#xff0c;实现了异步机制。Kafka中&#xff0c;消费者通常以消费者组…

解决方案| anyRTC远程检修应用场景

背景 在这个科技飞速发展的时代&#xff0c;各行各业都要求高效运转。然而&#xff0c;当出现问题时&#xff0c;我们却常常因为无法及时解决而感到困扰&#xff0c;传统解决问题的方式是邀请技术人员现场解决问题&#xff0c;如果技术人员解决不了&#xff0c;还要邀请专家从…

编程参考 - std::exchange和std::swap的区别

这两个功能是C standard library中的Standard template library中的一部分。容易混淆&#xff0c;我们来看下它们的区别。 exchange&#xff1a; 这个函数是一个返回原先值的set函数。 std::exchange is a setter returning the old value. int z std::exchange(x, y); Af…

C语言指针详解(3)———指针题目,你确定你学会指针了?进来看看吧!(几十个指针小题+超详解)

你确定你学会指针了&#xff1f; 你确定你明白数组名了&#xff1f; 如果你觉得你学的还不错&#xff0c;就进来看看吧&#xff0c;相信你看完之后一定能收获更多。 数组名的理解一定要弄清楚 数组名是数组首元素的地址 但是有2个例外&#xff1a; sizeof(数组名)&#xff0c;这…