什么是设计模式

设计模式,是软件开发过程中所面临问题的一般性解决方案,是众多开发人员在很长一段时间中的试验和错误中总结出来的最佳实践。

合理地使用设计模式可增强代码的可靠性和可重用性,同时也使得代码更容易被他人理解。

总的来说,设计模式可分为三大类:

  • 创建型 (Creation Patterns):提供一种 “隐藏了具体创建细节” 的对象创建方式。
  • 结构型 (Structual Patterns):聚焦于类和对象的组合。
  • 行为型 (Behavioral Patterns):聚焦于对象之间的通信。

创建型模式

单例模式

简介

单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。

优点

公共且不变的资源有且只会有一个对外的实例,避免不必要的内存占用。

缺点

  • 相应逻辑都写在一个对象里,很容易违背单一原则。
  • 不能扩展,违背开闭原则。

例子

懒汉式单例

当第一次调用 getlnstance 方法时才去创建这个单例。(例子是加了双锁的,但理论上也算是饿汉式)
多线程每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。

// 加了双锁保证线程安全,单线程环境是可以去除的
public class LazySingleton {  private volatile static LazySingleton instance;  private LazySingleton (){}  public static LazySingleton getInstance() {  if (instance == null) {  synchronized (LazySingleton.class) {  if (instance == null) {  instance = new LazySingleton();  }  }  }  return instance;  }  
}  

饿汉式单例

在初始化对象时就创建单例实例。

public class HungrySingleton {private static final HungrySingleton instance = new HungrySingleton();private HungrySingleton() {}public static HungrySingleton getInstance() {return instance;}
}

工厂方法

简介

顾名思义,就是创建一个工厂来新建对象。一般有四种角色:

  • 抽象对象:定义对象的抽象。
  • 具体对象:实现抽象对象。
  • 抽象工厂:定义工厂的抽象,定义创建对象的抽象方法。
  • 具体工厂:实现抽象工厂的抽象方法。

优点

  • 用户只需要知道具体工厂的名称就可得到所要的对象,无须知道对象的具体创建过程。
  • 灵活性增强,对于新类型对象的创建,只需多写一个相应的工厂类。
  • 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。

缺点

  • 对象每新增一个类型,都需要新增一个具体工厂,类的数量会很多。
  • 增加了系统的抽象性和理解难度。

例子

就拿奶茶店为例子,有珍珠奶茶跟水果奶茶,所以四种对象分别是:

  • 抽象奶茶:AbstractNaicha
  • 具体奶茶(珍珠奶茶、水果奶茶):ZhenzhuNaicha、ShuiguoNaicha
  • 奶茶店抽象工厂:AbstractNaichadianFactory
  • 奶茶店具体工厂(珍珠奶茶店工厂、水果奶茶店工厂):ZhenzhuNaichadianFactory、ShuiguoNaichadianFactory

// 抽象奶茶对象
interface AbstractNaicha{}// 珍珠奶茶
public class ZhenzhuNaicha implements AbstractNaicha {
}// 水果奶茶
public class ShuiguoNaicha implements AbstractNaicha {
}// 奶茶店抽象工厂
interface AbstractNaichadianFactory {public AbstractNaicha newNaicha();
}
// 珍珠奶茶店工厂,创建珍珠奶茶
class ZhenzhuNaichadianFactory implements AbstractNaichadianFactory {public AbstractNaicha newNaicha() {return new ZhenzhuNaicha();}
}
// 水果奶茶店工厂,创建水果奶茶
class ShuiguoNaichadianFactory implements AbstractNaichadianFactory {public AbstractNaicha newNaicha() {return new ShuiguoNaicha();}
}public static void main(String[] args) {// 先创建一个珍珠奶茶店工厂,再通过工厂创建一个珍珠奶茶AbstractNaichadianFactory aF = new ZhenzhuNaichadianFactory();AbstractNaicha zz = aF.newNaicha();// 先创建一个水果奶茶店工厂,再通过工厂创建一个水果奶茶AbstractNaichadianFactory bF = new ShuiguoNaichadianFactory();AbstractNaicha sg = bF.newNaicha();
}

抽象工厂

简介

跟工厂方法模式相比,无需每种对象都有一个具体工厂,因为抽象工厂中一个抽象工厂可包含多种同系列但是不同类型的创建对象的方法,依然是四种角色:

  • 抽象对象:定义对象的抽象。
  • 具体对象:实现抽象对象。
  • 抽象工厂:定义工厂的抽象,定义多种同系列但是不同类型创建对象的抽象方法。
  • 具体工厂:实现抽象工厂的抽象方法。

优点

与工厂方法模式一致。

缺点

与工厂方法模式一致。

例子

就拿奶茶店做例子,一个奶茶店工厂,可生产珍珠奶茶与水果奶茶,所以四种角色分别是:

  • 抽象奶茶:AbstractNaicha
  • 具体奶茶(珍珠奶茶、水果奶茶):ZhenzhuNaicha、ShuiguoNaicha
  • 奶茶店抽象工厂:AbstractNaichadianFactory
  • 奶茶店具体工厂:NaichadianFactory
// 抽象奶茶对象
interface AbstractNaicha{}// 珍珠奶茶
public class ZhenzhuNaicha implements AbstractNaicha {
}// 水果奶茶
public class ShuiguoNaicha implements AbstractNaicha {
}// 奶茶店抽象工厂
interface AbstractNaichadianFactory {public AbstractNaicha newZhenzhuNaicha();public AbstractNaicha newShuiguoNaicha();
}
// 奶茶店工厂,创建珍珠奶茶、水果奶茶
class NaichadianFactory implements AbstractNaichadianFactory {public AbstractNaicha newZhenzhuNaicha() {return new ZhenzhuNaicha();}public AbstractNaicha newShuiguoNaicha() {return new ShuiguoNaicha();}
}public static void main(String[] args) {// 创建一个奶茶店工厂AbstractNaichadianFactory aF = new ZhenzhuNaichadianFactory();// 通过工厂新建珍珠奶茶AbstractNaicha a = aF.newZhenzhuNaicha();// 通过工厂新建水果奶茶AbstractNaicha b = aF.newShuiguoNaicha();
}

建造者模式

简介

将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。这个模式最重要的是建造者对象,它是由四个部分组成:

  • 具体对象(Object):它是包含多个组成部件的具体对象,由具体建造者来创建其各个零部件。
  • 抽象建造者(AbstractBuilder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
  • 具体建造者(Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
  • 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

优点

  • 封装性好,构建和表示分离。
  • 扩展性好,各个具体的建造者相互独立,有利于系统的解耦。

缺点

对象的属性如果发生变化,建造者也要变化,维护成本加大。

例子

以奶茶为例子,一杯纯奶茶,你可以选择加珍珠,加椰果,打包带走等等。 那它的四个组成部分为:

  • 具体奶茶:Naicha
  • 抽象奶茶建造者:AbstractNaichaBuilder
  • 具体奶茶建造者:NaichaBuilder
  • 奶茶指挥者:NaichaBuilderDirector
class Naicha {private boolean zhenzhu;private boolean yegua;private boolean dabao;public void setZhenzhu(boolean isAdd) {this.zhenzhu = isAdd;}public void setYegua(boolean isAdd) {this.yegua = isAdd;}public void setDabao(boolean isAdd) {this.dabao = isAdd;}
}abstract class AbstractNaichaBuilder {protected Naicha naicha = new Naicha();public abstract void buildZhenzhu(boolean isAdd);public abstract void buildYegua(boolean isAdd);public abstract void buildDabao(boolean isAdd);//返回奶茶对象public Naicha build() {return naicha;}
}public class NaichaBuilder extends AbstractNaichaBuilder {public void buildZhenzhu(boolean isAdd) {product.setZhenzhu(isAdd);}public void buildYegua(boolean isAdd) {product.setYegua(isAdd);}public void buildDabao(boolean isAdd) {product.setDabao(isAdd);}
}class NaichaBuilderDirector {private AbstractNaichaBuilder builder;public Director(AbstractNaichaBuilder builder) {this.builder = builder;}// 是否加珍珠public AbstractNaichaBuilder zhenzhu(boolean isAdd) {builder.buildZhenzhu(isAdd);return builder;}// 是否加椰果public AbstractNaichaBuilder yeguo(boolean isAdd) {builder.buildYegua(isAdd);return builder;}// 是否打包public AbstractNaichaBuilder dabao(boolean isAdd) {builder.buildDabao(isAdd);return builder;}
}public static void main(String[] args) {// 新建构造者AbstractNaichaBuilder builder = new NaichaBuilder();// 新建指挥者NaichaBuilderDirector director = new NaichaBuilderDirector(builder);// 新建奶茶对象Naicha naicha = director.zhenzhu(true).yeguo(true).dabao(true).build();
}

原型模式

简介

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。其中跟这个模式相关的有2个概念:

  • 浅拷贝:只是增加了一个指针指向原型对象的内存地址,仅仅是指向被复制的内存地址,如果原地址发生改变,那么浅复制出来的对象也会相应的改变。
  • 深拷贝:增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,并把原型对象的属性全部拷贝过来。

java有Cloneable来实现浅拷贝。

行为型模式

模板方法

简介

定义一个操作中的方法骨架,而将方法的一些步骤延迟到子类中,使得子类可以不改变该方法的逻辑结构的情况下重定义某些特定步骤,它分三部分组成:

  • 模板方法:定义了方法骨架,骨架内的方法按顺序来执行,一般包含抽象方法、具体方法。
  • 抽象方法:对外扩展的方法,由子类实现。
  • 具体方法:由父类实现,不允许子类修改。

优点

  • 父类封装了不变部分方法,并对子类扩展可变部分方法。
  • 符合开闭原则。

缺点

  • 扩展方法的每种实现都需要定义一个子类,整个类群会很大。
  • 父类新增抽象方法的话,全部子类都需要新增实现。

例子

用户去奶茶店买奶茶,步骤分别是排队、点餐、叫号,其中点餐是可扩展给用户去自定义的,所以三部分为:

  • 模板方法:买奶茶。
  • 抽象方法:点餐。
  • 具体方法:排队,叫号。

public abstract class NaichaDian {// 买奶茶的入口public void maiNaicha() {paidui();diancan();jiaohao();}// 排队private void paidui() {// 由奶茶店实现排队规则   }// 点餐,用户想吃啥自己决定public abstract void diancan();// 叫号private void paidui() {// 由奶茶店实现叫号规则   }}public class User1 extends NaichaDian {@Overridepublic void diancan(){// 我要喝珍珠奶茶   }
}public class User2 extends NaichaDian {@Overridepublic void diancan(){// 我要喝水果奶茶   }
}public static void main(String[] args) {User1 u1 = new User1();// 用户1去买一杯珍珠奶茶u1.maiNaicha();User1 u2 = new User1();// 用户2去买一杯水果奶茶u2.maiNaicha();
}

中介者模式

简介

定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,迪米特法则的典型应用。它由四个角色组成:

  • 抽象中介者(AbstractMediator):它是中介者的接口,提供了实例对象之间的交互功能的抽象方法。
  • 具体中介者(Mediator)角色:实现中介者接口,定义一个 List 来管理抽象对象,协调各个实例对象之间的交互关系,因此它依赖于抽象对象类。
  • 抽象对象类(AbstractObject):定义实例对象类的接口,保存中介者对象,提供实例对象交互的抽象方法,实现所有相互影响的实例对象类的公共功能。
  • 具体对象类(Object):是抽象对象类的实现者,当需要与其他实例对象交互时,由中介者对象负责后续的交互。

优点

降低对象之间的耦合性,符合迪米特原则。

缺点

未有明显缺点。

例子

最贴近的就是网络聊天室的例子,小A跟小B都在聊天室注册自己的信息,然后发消息跟接消息都通过聊天室转发,于是四个角色为:

  • 抽象中介者:AbstractChatMediator
  • 具体中介者** **:ChatMediator。
  • 抽象对象类:AbstractUser。
  • 具体对象类:UserA、UserB。
public abstract class AbstractChatMediator {// 注册用户public abstract void register(User user);// 转发消息public abstract void relay(User user, String msg);
}public class ChatMediator {private Map<Integer, User> users = new HashMap<>();// 注册用户到自己的用户列表里public void register(User user) {users.put(user.id, user);}// 转发给目标用户public void relay(Integer id, String msg) {// 这里默认该用户一定在注册到列表里users.get(id).receive(id, msg)}
}public abstract class User {// 用户必须依赖中介protected AbstractChatMediator mediator;public void setMediator(AbstractChatMediator mediator) {this.mediator = mediator;}// 接收指定id的消息public abstract void receive(Integer id, String msg);// 发送指定id的消息public abstract void send(Integer id, String msg);
}public class UserA extends User {public Integer id = 1;// 接收指定id的消息public void receive(Integer id, String msg){// 怎么处理UserA自己决定。}// 发送指定id的消息public void send(Integer id, String msg){// 让中介者转发mediator.relay(id, msg);}
}public class UserB extends User {public Integer id = 2;// 接收指定id的消息public void receive(Integer id, String msg){// 怎么处理UserB自己决定。}// 发送指定id的消息public void send(Integer id, String msg){// 让中介者转发mediator.relay(id, msg);}
}public static void main(String[] args) {User ua = new UserA();  User ub = new UserB();// a 向 b 发消息ua.send(2, "hello");// b 向 a 发消息ub.send(1, "hello");
}

命令模式

简介

将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。它由四种角色组成:

  • 抽象命令类(AbstractCommand):声明执行命令的接口,一般拥有执行命令的抽象方法 execute()。
  • 具体命令类(Command):是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
  • 实现者/接收者(Receiver):执行命令功能的相关操作,是具体命令对象业务的真正实现者。
  • 调用者/请求者(Invoker):是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。

优点

扩展性良好,增加或删除命令非常方便,并且不会影响其他类,符合开闭原则。

缺点

可能产生大量具体的命令类。因为每一个具体操作都需要设计一个具体命令类,这会增加系统的复杂性。

例子

奶茶店买喝的,用户打开小程序,点了一份珍珠奶茶然后下单,这时候“制作珍珠奶茶”的命令就传给了奶茶店,后来用户觉得不够喝,又点了一份水果奶茶然后下单,“制作水果奶茶”的命令传给了奶茶店,后来发现吃太多会胖的,于是又取消了水果奶茶的订单,“取消水果奶茶”的命令传给了奶茶店。

  • 抽象命令类:AbstractNaichaCommand
  • 具体命令类:MakeZhenzhuNaichaCommand制作珍珠奶茶、MakeShuiguoNaichaCommand制作水果奶茶、CancelShuiguoNaichaCommand取消水果奶茶
  • 实现者/接收者:NaichadianReceiver
  • 调用者/请求者:UserInvoker

// 奶茶店接收者
class NaichadianReceiver {// 开始制作奶茶public void make(String name) {}// 停止制作奶茶public void stop(String name) {}
}// 抽象奶茶命令
interface AbstractNaichaCommand {public void execute();
}// 制作珍珠奶茶命令
class MakeZhenzhuNaichaCommand implements AbstractNaichaCommand {private NaichadianReceiver receiver;public ZhenzhuNaichaCommand(NaichadianReceiver receiver) {this.receiver = receiver;}// 把制作珍珠奶茶命令给奶茶店@Overridepublic void execute() {receiver.make("珍珠");}
}// 制作水果奶茶命令
class MakeShuiguoNaichaCommand implements AbstractNaichaCommand {private NaichadianReceiver receiver;public ShuiguoNaichaCommand(NaichadianReceiver receiver) {this.receiver = receiver;}// 把制作水果奶茶命令给奶茶店@Overridepublic void execute() {receiver.make("水果");}
}// 取消制作水果奶茶命令
class CancelShuiguoNaichaCommand implements AbstractNaichaCommand {private NaichadianReceiver receiver;public ShuiguoNaichaCommand(NaichadianReceiver receiver) {this.receiver = receiver;}// 把制作水果奶茶命令给奶茶店@Overridepublic void execute() {receiver.cancel("水果");}
}// 用户请求者
class UserInvoker {// 下单、取消订单、评论....public void action(AbstractNaichaCommand command) {command.execute();}
}public static void main(String[] args) {// 先创建一个奶茶店接收者NaichadianReceiver receiver = new NaichadianReceiver();// 再创建一个用户请求者UserInvoker invoker = new Invoker();// 下单珍珠奶茶invoker.action(new MakeZhenzhuNaichaCommand(receiver));// 下单水果奶茶invoker.action(new MakeShuiguoNaichaCommand(receiver));// 取消水果奶茶invoker.action(new CancelShuiguoNaichaCommand(receiver));
}

责任链模式

简介

为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。主要包含以下角色:

  • 抽象处理者(AbstractHandler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  • 具体处理者(Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

优点

  • 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
  • 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。

缺点

  • 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
  • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  • 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

例子

小红请假会经过层层管理者的审批,比如小红-部门经理-区域经理-老板。请三天以下,部门经理可以直接同意,五天以下区域经理可以直接同意,请三十天以下老板直接同意,但是大于三十天就直接拒绝。这三种角色分别为:

  • 抽象处理者:AbstractHandler
  • 具体处理者:BumenJingliHandler、QuyuJingliHandler、BossHandler
  • 客户类:XiaohongClient
public abstract AbstractHandler {private AbstractHandler nextHandler;public void setNextHandler(AbstractHandler handler){this.nextHandler = handler;}public AbstractHandler getNextHandler() {return nextHandler;}// 处理请假public abstract Boolean handlerQingjia(int day);
}public class BumenJingliHandler extends AbstractHandler {// 不小于三天,可以直接同意,否则转到下一级@Overridepublic Boolean handlerQingjia(int day) {if (day <= 3) {return true   } else {return getNextHandler().handlerQingjia(day);}}
}public class QuyuJingliHandler extends AbstractHandler {// 不小于五天,可以直接同意,否则转到下一级@Overridepublic Boolean handlerQingjia(int day) {if (day <= 5) {return true   } else {return getNextHandler().handlerQingjia(day);}}
}public class BossHandler extends AbstractHandler {// 不小于三十天,可以直接同意,否则拒绝@Overridepublic Boolean handlerQingjia(int day) {if (day <= 30) {return true   } else {return false;}}
}// 小红
public class XiaohongClient {private AbstractHandler handle;public Xiaohong(AbstractHandler handle) {this.handle = handle;}// 请假会先给直接关联的处理者public Boolean handlerQingjia(int day) {return handle.handlerQingjia(day);}
}public static void main(String[] args) {BossHandler boss = new BossHandler(); QuyuJingliHandler quyuJingli = new QuyuJingliHandler();BumenJingliHandler bumenJingli = new BumenJingliHandler();// 小红跟部门经理直接关联XiaohongClient xiaohong = new XiaohongClient(bumenJingli);// 部门经理的下级是区域经理bumenJingli.setNextHandler(quyuJingli);// 区域经理的下级是老板bumenJingli.setNextHandler(boss);// 小红开始请假4天,不出意外部门经理就可以同意xiaohong.handlerQingjia(4);
}

策略模式

简介

该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。策略模式的主要角色如下:

  • 抽象策略(AbstractStrategy):定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
  • 具体策略(Strategy):实现了抽象策略定义的接口,提供具体的算法实现。
  • 环境(Context):持有一个策略类的引用,最终给客户端调用。

优点

策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。

缺点

  • 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
  • 策略模式造成很多的策略类,增加维护难度。

例子

出去旅游,可以坐火车、坐高铁、搭飞机到达旅游目的地。这三种角色分别是:

  • 抽象策略:AbstractStrategy(抽象行程方式策略)
  • 具体策略:HuocheStrategy、GaotieStrategy、FeijiStrategy
  • 环境:Context
interface AbstractStrategy {public void execute();   
}public class HuocheStrategy implements AbstractStrategy {@Overridepublic void execute() {// 买火车票,准备行李,去火车站,上车   }
}public class GaotieStrategy extends AbstractStrategy {@Overridepublic void execute() {// 买高铁票,准备行李,去高铁站,上车   }
}public class FeijiStrategy extends AbstractStrategy {@Overridepublic void execute() {// 买飞机票,准备行李,去飞机站,上飞机  }
}public class Context {private AbstractStrategy strategy;public Context(AbstractStrategy strategy) {this.strategy = strategy;  }// 决定什么行程工具策略public void execute() {strategy.execute();}}public static void main(String[] args) {// 还是坐高铁吧Context context = new Context(new GaotieStrategy());context.execute();
}

迭代器模式

简介

提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。java中集合提供了Iterator这种迭代类,比较容易理解,所以不去过多解说。

观察者模式

简介

指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,观察者模式的主要角色如下:

  • 抽象主题(AbstractSubject):也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
  • 具体主题(Subject):也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  • 抽象观察者(AbstractObserver):它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
  • 具体观察者(Observer):实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

优点

降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。

缺点

当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。

例子

小红、小绿在微信关注了Xx公众号,当Xx公众号有更新时,就会通知关注的用户小红、小绿。这四种角色为:

  • 抽象主题:AbstractGongzhonghaoSubject。
  • 具体主题:XxGongzhonghaoSubject。
  • 抽象观察者:AbstractObserver 用户观察者。
  • 具体观察者:XiaohongObserver、XiaolvObserver。
interface AbstractObserver  {// 接收主题的通知并进行处理void receive();
}public class XiaohongObserver implements AbstractObserver {@Overridepublic void receive() {// 小红发现公众号更新了,赶紧去看一波   }
}public class XiaolvObserver implements AbstractObserver {@Overridepublic void receive() {// 小绿发现公众号更新了,不鸟它  }
}interface AbstractGongzhonghaoSubject {// 关注void guanzhu(AbstractObserver observer);// 取消关注void quxiaoGuanzhu(AbstractObserver observer);// 更新内容void gengxin();
}public class XxGongzhonghaoSubject implements AbstractGongzhonghaoSubject {// 关注者列表List<AbstractObserver> observers = new ArrayList<>();// 关注@Overridepublic void guanzhu(AbstractObserver observer) {observers.add(observer);}// 取消关注@Overridepublic void quxiaoGuanzhu(AbstractObserver observer) {observers.remove(observer);}// 更新内容,通知关注者们@Overridepublic void gengxin(){for(AbstractObserver observer: observers) {observer.receive();}}
}public static void main(String[] args) {XiaohongObserver xiaohong = new XiaohongObserver();XiaolvObserver xiaolv = new XiaolvObserver();AbstractGongzhonghaoSubject xxSubject = new XxGongzhonghaoSubject();// 小红小绿先关注一波Xx公众号(这里例子不太好,就好像是公众号关注了他俩,但能理解就行)xxSubject.guanzhu(xiaohong);xxSubject.guanzhu(xiaolv);// xx公众号开始更新内容,通知他们xxSubject.gengxin();}

状态模式

简介

对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。状态模式包含以下主要角色:

  • 环境类(Context):也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态对象的切换。
  • 抽象状态(AbstractState):定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。
  • 具体状态(State):实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。

优点

结构清晰,状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。

缺点

  • 状态越多,对象越多。
  • 状态模式对开闭原则的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源码,否则无法切换到新增状态,而且修改某个状态类的行为也需要修改对应类的源码。

例子

请假,那请假状态就可以是未申请、已申请未审批、已审批三种状态,所以三种角色分别为:

  • 环境类:QingjiaContext。
  • 抽象状态:AbstractQingjiaState
  • 具体状态:NotShenqingState未申请、NotShenpiState未审批、YiShenpiState已审批通过。
public abstract class AbstractQingjiaState {private QingjiaContext context;public void setContext(QingjiaContext context) {this.context = context;   }// 申请请假public abstract bool shenqing();// 审批申请public abstract bool shenpi();
}// 还没申请
public class NotShenqingState extends AbstractQingjiaState {// 申请请假,并把上下文的状态改成下一个状态public bool shenqing(){this.setContext(new NotShenpiState());return true;}// 还没申请,当然没到审批那一步public bool shenpi(){return false;   }
}// 还没审批
public class NotShenpiState extends AbstractQingjiaState {// 已经申请,不需要再次申请public bool shenqing() {return false;}// 审批申请,并把上下文的状态改成下一个状态public bool shenpi(){this.setContext(new YiShenpiState());return true;   }
}// 已审批,属于最终状态了,所以对于的行为都是返回false,不成功
public class YiShenpiState extends AbstractQingjiaState {public bool shenqing() {return false;}public bool shenpi() {return false;   }
}public class QingjiaContext {private AbstractQingjiaState state;// 初始化请假上下文时,请假的状态还是未申请。public QingjiaContext() {this.state = new NotShenqingState();   }public void setState(AbstractQingjiaState state) {this.state = state   }public void getState() {return state}// 申请请假public bool shenqing(){return this.state.shenqing();}// 审批申请public bool shenpi(){return this.state.tongguo();   }
}public static void main(String[] args) {// 可以设定两种场景// 正常的流程,申请,审批,获取请假状态,最终的状态肯定是已审批QingjiaContext c1 = new QingjiaContext();c1.shenqing();c1.shenpi();c1.getState();// 不正常的流程,直接审批,然后获取请假状态,最终的状态是未申请QingjiaContext c1 = new QingjiaContext();c1.shenpi();c1.getState();// 其实每种请求行为都会返回布尔值,可根据这个布尔值判断当前的请假行为流程是否有效。}

备忘录模式

简介

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态,该模式又叫快照模式。模式有三种角色:

  • 发起者(Originator):记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
  • 备忘录(Memento):负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
  • 管理者(Caretaker):对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

优点

提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态。

缺点

资源消耗大。

例子

游戏的存档机制,就是备忘录模式。游戏提供存档、读档2个功能,存档文件保存游戏进度的状态,存档管理者就管理存档文件。所以三种角色为:

  • 发起者:GameOriginator
  • 备忘录:CundangMemento
  • 管理者:CundangCaretaker

public class CundangMemento {
}public class CundangCaretaker {private List<CundangMemento> mementos = new ArrayList<>();// 获取存档列表public List<CundangMemento> getMementos() {return mementos;}// 保存存档public void save(CundangMemento memento) {mementos.add(memento);}// 读档public CundangMemento dudang(Integer state){return caretaker.get(state);}// 后续可加覆盖档、删档..
}public class GameOriginator {private CundangCaretaker caretaker = new CundangCaretaker();// 获取存档列表public List<CundangMemento> getMementos() {return caretaker.getMementos();    }// 存档public void save() {return new CundangMemento();}// 读档public CundangMemento dudang(Integer state){return caretaker.dudang(state);}
}public static void main(String[] args) {// 创建游戏(自带存档管理器)GameOriginator originator = new GameOriginator();// 存档originator.save();// 获取存档列表originator.getMementos();// 可根据存档列表选择想读取的存档,这里省略获取列表下标的步骤,直接假设一个1来进行读档。originator.dudang(1);
}

解释器模式

简介

给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。模式有以下角色:

  • 抽象表达式(Abstract Expression):定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
  • 终结符表达式(Terminal Expression):是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
  • 非终结符表达式(Nonterminal Expression):也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
  • 环境(Context):通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
  • 客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。

解释器模式在实际的软件开发中使用比较少,因为它会引起效率、性能以及维护等问题,所以这里不展开讲,有兴趣的童鞋可自行查阅相关资料。

访问者模式

简介

将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。模式有几种角色:

  • 抽象访问者(AbstractVisitor):定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。visit方法个数理论上与元素的个数是一样的,因此,访问者模式要求元素的类型要稳定,如果经常添加、移除元素类,必然会导致频繁地修改 AbstractVisitor接口,如果出现这种情况,则说明不适合使用访问者模式。
  • 具体访问者(Visitor):实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
  • 抽象元素(AbstractElement):声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
  • 具体元素(Element):实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
  • 对象结构(ObjectStructure):是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。

适用场景

通常在以下情况可以考虑使用访问者模式:

  • 对象结构相对稳定,但其操作算法经常变化的程序。
  • 对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构。
  • 对象结构包含很多类型的对象,希望对这些对象实施一些依赖于其具体类型的操作。

优点

  • 扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
  • 复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。
  • 灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
  • 符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。

缺点

  • 破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性。
  • 违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类。

例子

奶茶店有2种奶茶,珍珠奶茶、水果奶茶,非会员原价买,而会员则可打9折。所以这几种角色为:

  • 抽象访问者:AbstractVisitor
  • 具体访问者:NoHuiyuanVisitor非会员访问者、HuiyuanVisitor会员访问者
  • 抽象元素:AbstractNaichaElement
  • 具体元素:ZhenzhuNaichaElement珍珠奶茶、ShuiguoNaichaElement水果奶茶
  • 对象结构:NaichadianStructure奶茶店
interface AbstractVisitor {// 访问者去买珍珠奶茶的价格double visit(ZhenzhuNaichaElement elemen);// 访问者去买水果奶茶的价格double visit(ShuiguoNaichaElement elemen);// 后续如果有新的类型奶茶,都在这里加即可
}// 非会员买各种奶茶的价格都是原价
public class NoHuiyuanVisitor implements AbstractVisitor {public double visit(ZhenzhuNaichaElement elemen){return elemen.getPrice();}public double visit(ShuiguoNaichaElement elemen){return elemen.getPrice();}
}// 会员买各种奶茶的价格都是打9折
public class NoHuiyuanVisitor implements AbstractVisitor {public double visit(ZhenzhuNaichaElement elemen){return elemen.getPrice() * 0.9;}public double visit(ShuiguoNaichaElement elemen){return elemen.getPrice() * 0.9;}
}public abstract class AbstractNaichaElement {private double price;public AbstractNaichaElement(double price){this.price=price;}public double getPrice() {return price;}abstract double accept(AbstractVisitor visitor);
}public class ZhenzhuNaichaElement extends AbstractNaichaElement {public ZhenzhuNaichaElement(double price) {super(price);}@Overridepublic double accept(AbstractVisitor visitor) {return visitor.visit(this);}
}public class ShuiguoNaichaElement extends AbstractNaichaElement {public ShuiguoNaichaElement(double price) {super(price);}@Overridepublic double accept(AbstractVisitor visitor) {return visitor.visit(this);}
}public class NaichadianStructure {List<AbstractNaichaElement> elements = new ArrayList<>();// 这里可遍历奶茶对象,通过传入的会员类型来获取全部奶茶的价格public void accept(AbstractVisitor visitor) {for(AbstractNaichaElement element: elements) {// 获取不同的价格element.accept(visitor);}}public void add(AbstractNaichaElement element) {elements.add(element);}
}public static void main(String[] args) {// 新建奶茶店NaichadianStructure naichadian = new NaichadianStructure();// 新建2种奶茶naichadian.add(new ZhenzhuNaichaElement(10));naichadian.add(new ShuiguoNaichaElement(10));// 非会员查看全部奶品的价格naichadian.accept(new NoHuiyuanVisitor());// 会员查看全部奶品的价格naichadian.accept(new HuiyuanVisitor());}

结构型模式

适配器模式

简介

将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式包含以下主要角色:

  • 目标接口(Target):当前系统业务所期待的接口,它可以是抽象类或接口。
  • 适配者(Adaptee):它是被访问和适配的现存组件库中的组件接口。
  • 适配器(Adapter):它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

优点

  • 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
  • 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
  • 在很多业务场景中符合开闭原则。

缺点

增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。

例子

苹果数据线有充电,绑东西的作用,现在华为手机充电,但现在只有苹果数据线、转换器,转换器支持苹果数据线头转安卓数据线头,于是把苹果线头插到转换器里,华为使用转换器就可以通过苹果数据线来充电了,这几个角色为:

  • 目标接口:HuaweiTarget
  • 适配者():PingguoAdaptee
  • 适配器():Pingguo2HuaweiAdapter苹果转华为

interface HuaweiTarget {void chongdian();   
}public class PingguoAdaptee {public void chongdian() {  }// 苹果数据线不单单可充电,有时可以作为一个绳子绑东西用的public void bangDongxi() {  }
}public class Pingguo2HuaweiAdapter extends PingguoAdaptee implements HuaweiTarget {@Overridepublic void chongdian() {// 转换器把苹果充电的功能改一下,改成适合安卓的  }
}public static void main(String[] args) {Pingguo2HuaweiAdapter adapter = new Pingguo2HuaweiAdapter();// 给华为充电adapter.chongdian();// 绑东西adapter.bangDongxi();
}

桥接模式

简介

将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。桥接模式包含以下主要角色:

  • 抽象化(AbstractObject):定义抽象类,并包含一个对实现化对象的引用。
  • 扩展抽象化(RefinedAbstracttObject):是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
  • 实现化(AbstractImplementor):定义实现化角色的接口,供扩展抽象化角色调用。
  • 具体实现化(Implementor):给出实现化角色接口的具体实现。

适用场景

桥接模式的一个常用使用场景就是为了替换 继承,继承本身具备强侵入性(父类代码侵入子类),造成子类臃肿,因此,优先使用组合/聚合的方式。
桥接模式的特点是将抽象与实现分离,因此它适合

  • 一个类存在两个或多个独立变化的维度,而且这两个维度都需要扩展
  • 不希望或不适用继承的场景

优点

  • 抽象与实现分离,扩展能力强
  • 符合开闭原则

缺点

例子

奶茶店卖奶茶,按种类分是有珍珠奶茶、水果奶茶,按分量分是有中杯、大杯。,只要在分量里携带种类,就可组合种类跟分量来进行买奶茶,所以四种角色为:

  • 抽象化:AbstractFenliang
  • 扩展抽象化:ZhongFenliang、DaFenliang
  • 实现化:AbstractZhonglei
  • 具体实现化:ZhenzhuZhonglei、ShuiguoZhonglei


interface AbstractZhonglei {void add();
}public class ZhenzhuZhonglei implements AbstractZhonglei {public void add(){// 珍珠奶茶  }
}public class ShuiguoZhonglei implements AbstractZhonglei {public void add(){// 水果奶茶   }
}public abstract class AbstractFenliang {protected AbstractZhonglei zhonglei;public Abstraction(AbstractZhonglei zhonglei) {this.zhonglei = zhonglei;}abstract void add();
}public class ZhongFenliang AbstractFenliang {public Abstraction(AbstractZhonglei zhonglei) {super(zhonglei);}  public void add(){// 中杯// + 种类zhonglei.add();}
}public class DaFenliang AbstractFenliang {public Abstraction(AbstractZhonglei zhonglei) {super(zhonglei);}public void add(){// 大杯   // + 种类zhonglei.add();}
}public static void main(String[] args) {// 大杯珍珠奶茶new DaFenliang(new ZhenzhuZhonglei());// 中杯水果奶茶new ZhongFenliang(new ShuiguoZhonglei());
}

组合模式

简介

时又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性。
理论上就是一个树状的数据模式,用的并不多,有兴趣的童学可自行上网查阅。

装饰模式

简介

在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。装饰器模式主要包含以下角色:

  • 抽象构件(AbstractComponent):定义一个抽象接口以规范准备接收附加责任的对象。
  • 具体构件(Cmponent):实现抽象构件,通过装饰角色为其添加一些职责。
  • 抽象装饰(AbstractDecorator):继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  • 具体装饰(Decorator):实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

优点

  • 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
  • 装饰器模式完全遵守开闭原则

缺点

例子

手抓饼,你可以让老板加鸡蛋、加火腿…,这样的话,四种角色为:

  • 抽象构件:AbstractShouzhuabingComponent
  • 具体构件:ShouzhuabingComponent
  • 抽象装饰:AbstractShouzhuabingDecorator
  • 具体装饰:JidanDecorator、HuotuiDecorator


interface AbstractShouzhuabingComponent {public void add();
}class ShouzhuabingComponent implements AbstractShouzhuabingComponent {public void add() {// 添加一个手抓饼}
}class AbstractShouzhuabingDecorator implements AbstractShouzhuabingComponent {private AbstractShouzhuabingComponent component;public AbstractShouzhuabingDecorator(AbstractShouzhuabingComponent component) {this.component = component;}public void add() {component.add();}
}
// 鸡蛋
class JidanDecorator extends AbstractShouzhuabingDecorator {public JidanDecorator(AbstractShouzhuabingComponent component) {super(component);}public void add() {super.add();// 在别的装饰基础上加个鸡蛋}
}// 火腿
class HuotuiDecorator extends AbstractShouzhuabingDecorator {public HuotuiDecorator(AbstractShouzhuabingComponent component) {super(component);}public void add() {super.add();// 在别的装饰基础上加个火腿}
}public static void main(String[] args) {// 先来个手抓饼ShouzhuabingComponent shouzhuabing = new ShouzhuabingComponent();// 加个鸡蛋JidanDecorator jidan = new JidanDecorator(shouzhuabing);// 加个火腿HuotuiDecorator huotui = new HuotuiDecorator(jidan);
}

外观模式

简介

又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。三个角色:

  • 外观(Facade):为多个子系统对外提供一个共同的接口。
  • 子系统(Sub System):实现系统的部分功能,客户可以通过外观角色访问它。
  • 客户(Client):通过一个外观角色访问各个子系统的功能。

优点

  • 降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类。

缺点

  • 增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

例子

小时候读小学时,没钱了,直接问妈妈要5毛钱买辣条吃,于是妈妈打开柜子,打开存钱罐,拿出5毛钱,然后给我。对于我来说,只需要知道我问妈妈要钱即可,无需知道妈妈怎么变出钱来的。于是三种角色为:

  • 外观:MotherFacade
  • 子系统:Dakaiguizi、DakaiCunqianguang、Nachu5
  • 客户:MeClient

public class MotherFacade {private Dakaiguizi dakaiguizi = new Dakaiguizi();private DakaiCunqianguang dakaiCunqianguang = new DakaiCunqianguang();private Nachu5 nachu5 = new Nachu5();// 给钱public void geiqian() {// 打开柜子,打开存钱罐,拿出5毛钱dakaiguizi.do();dakaiCunqianguang.do();nachu5.do();}
}public class Dakaiguizi {public void do(){// 打开柜子}
}public class DakaiCunqianguang {public void do(){// 打开存钱罐}
}public class Nachu5 {public void do(){// 拿出5毛钱}
}public class MeClient {// 向妈妈要钱public void yaoqian(MotherFacade mother){mother.geiqian();}
}public static void main(String[] args) {MotherFacade mother = new MotherFacade();MeClient me = new MeClient();me.yaoqian(mother);
}

享元模式

简介

运用共享技术来有效地支持大量细粒度对象的复用。享元模式的主要角色有如下。

  • 抽象享元角色(AbstractFlyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口。
  • 具体享元(Flyweight):实现抽象享元角色中所规定的接口。
  • 享元工厂(FlyweightFactory):负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

其中可扩展的是,内部状态与外部状态,也就是享元部分与非享元部分。java的线程池就是用了享元模式,非享元部分就是对线程池的配置,享元部分就是复用的线程池。

优点

相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。

缺点

读取状态会消耗更多时间。

例子

妈妈在厨房做菜,然后用同一个国产铁锅就可以炒鸡蛋、炒白菜了,当然妈妈还有一个进口铁锅。所以三种角色是:

  • 抽象享元角色:AbstractZuocaiFlyweight做菜享元角色
  • 具体享元:TieguoFlyweight铁锅享元
  • 享元工厂:TieguoFlyweightFactory铁锅享元工厂

// 因为可能扩展为内外状态,所以是抽象类作为父类
public abstract class AbstractZuocaiFlyweight {abstract void do();
}public class TieguoFlyweight extends AbstractZuocaiFlyweight {private String name;public TieguoFlyweight(String name) {this.name = name;   }@Overridepublic void do(){// 铁锅开始炒菜   }
}public class TieguoFlyweightFactory {Map<String, TieguoFlyweight> tieguos = new HashMap<>();public TieguoFlyweight getTieguoFlyweight(String name) {if tieguos.containsKey(name) {return tieguos.get(name);} else {return tieguos.put(name, new TieguoFlyweight())}}
}public static void main(String[] args) {TieguoFlyweightFactory factory = new TieguoFlyweightFactory();// 妈妈要拿出国产铁锅炒鸡蛋、炒白菜factory.getTieguoFlyweight("国产铁锅");// 觉得味道不好,又拿出进口铁锅炒胡萝卜factory.getTieguoFlyweight("进口铁锅");
}

代理模式

简介

由于某些原因需要给某对象提供一个代理以控制对该对象的访问。代理模式的主要角色如下:

  • 抽象主题(AbstractSubject):通过接口或抽象类声明真实主题和代理对象实现的业务方法。
  • 真实主题(Subject):实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  • 代理(Proxy):提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

优点

  • 代理对象可以扩展目标对象的功能
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性

例子

小明想去法国购买法国香水,但是又不想自己去法国买,于是他找了一个代购,通过他来买到法国香水。所以三种角色为:

  • 抽象主题:AbstractFaguoSubject
  • 真实主题:FaguoSubject
  • 代理:DaigouProxy
interface AbstractFaguoSubject {void buy(String name);   
}public class FaguoSubject implements AbstractXiangshuiSubject {public void buy(String name){// 去法国买什么}
}public class DaigouProxy {private AbstractFaguoSubject faguo;public DaigouProxy(AbstractFaguoSubject faguo) {this.faguo = faguo;   }public void buy(String name) {this.faguo.buy(name);   }}public static void main(String[] args){// 创建个法国AbstractFaguoSubject faguo = new FaguoSubject();// 创建个代购DaigouProxy daigou = new DaigouProxy(faguo);daigou.buy("法国香水");// 以后想去法国买啥都可以通过代购来买。
}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 使用Python+OpenCV实现姿态估计

    本文链接&#xff1a;使用PythonOpenCV实现姿态估计_深度学习与计算机视觉-CSDN博客 版权 什么是OpenCV&#xff1f; 计算机视觉是一个能够理解图像和视频如何存储和操作的过程&#xff0c;它还有助于从图像或视频中检索数据。计算机视觉是人工智能的一部分。 计算机视觉在…...

    2024/4/7 16:39:44
  2. MCCNN

    Automatic Detection and Classification System of Domestic Waste via Multi- model Cascaded Convolutional Neural Network 基于多模型级联卷积神经网络的生活垃圾自动检测分类系统 1.摘要: 生活垃圾分类是我国最近才纳入法律规定的。然而&#xff0c;依靠人力来检测和分类…...

    2024/4/22 13:20:26
  3. 宿舍信息管理系统(1),100%好评

    void paixumenu() //排序函数 { string choice; int i,m,j; system(“cls”); cout<<“请输入排序的方式&#xff08;1&#xff1a;按学号排序&#xff0c;2&#xff1a;按房号排序&#xff0c;3&#xff1a;按名字排序&#xff09;&#xff1a;”<<endl; //三…...

    2024/4/7 16:39:42
  4. 深度强化学习-Pytorch1.6环境配置

    引言 “工欲善其事&#xff0c;必先利其器”&#xff0c;环境配置是开展Coding的第一步。我用过TensorFlow和Pytorch两种深度学习框架&#xff0c;对比下来更喜欢Pytorch。如果有小伙伴纠结使用哪个框架&#xff0c;我更加推荐Pytorch。本文主要跟大家讲解一下如何搭建Pytorch…...

    2024/4/17 22:51:00
  5. 算法06——patA1016电话账单问题(配对排序求和)

    题目描述&#xff1a;   给出24h中每个小时区间的资费(cents/minute)&#xff0c;并给出N个通话记录点&#xff0c;每个通话记录点都记录了姓名、当前的时刻(月&#xff1a;日&#xff1a;时&#xff1a;分)以及其属于通话开始(on-line)或是通话结束(off-line)。现在需要对每…...

    2024/4/19 12:14:54
  6. 斐波那契数列python

    感觉网上有些代码有点复杂&#xff0c;整理了斐波那契数列的递推和递归两种写法。都是输入n之后&#xff0c;答案给出第n个数是几。 递推代码 python fib [0 for i in range(100000)] n int(input()) def fibo():fib[0],fib[1] 1,1for i in range(2,n):fib[i] fib[i-1] …...

    2024/4/14 6:09:41
  7. 前端工程师的摸鱼日常(13)

    上上周六&#xff0c;我去找了我的牛马朋友&#xff01;他媳妇要生了得赶快回襄阳&#xff0c;不出意外的话过年他会在医院待着&#xff0c;而我会很晚回去&#xff0c;开年也会来的比较早&#xff0c;所以想着今年最后一次小聚&#xff01; 我下午过去的时候&#xff0c;这人…...

    2024/4/14 6:10:32
  8. 文件传输协议:FTP(和HTTP的异同)

    一个典型的FTP会话 用户坐在一台主机&#xff08;本地主机&#xff09;前面&#xff0c;向一台远程主机传输&#xff08;或接收来自远程主机的)文件。为使用户能访问它的远程账户&#xff0c;用户必须提供一个用户标识和口令。在提供了这种授权信息后&#xff0c;用户就能从本…...

    2024/4/16 16:34:52
  9. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

    1.Abstract 我们介绍了一种新的语言表示模型BERT&#xff0c;它表示转换器的双向编码器表示。与最近的语言表示模型不同(Peters et al., 2018; Radford et al., 2018)&#xff0c;BERT通过在所有层的上下文联合调节来预训练深层双向表示。因此&#xff0c;只需一个额外的输出层…...

    2024/4/19 0:22:47
  10. 关于 moveit_commander 的 conversions 问题

    AttributeError: RobotTrajectory object has no attribute serializeArray 修改conversions.py 中此段代码&#xff1a; def msg_to_string(msg):buf StringIO()msg.serialize(buf) # 修改了此处return buf.getvalue() 搞定。...

    2024/4/20 14:51:48
  11. [PHP]文件上传利用的常见函数

    前言 收集了几个在文件上传利用中常见的函数。 对这些函数的深入理解应该有助于文件上传利用的顺利进行。 索引 1. deldot 2. in_array 3. intval 4. strrchr 5. strtolower 6. strrpos 7. str_ireplace 8. strstr 9. substr 10. trim 常见函数 1. deldot deldot…...

    2024/4/7 16:39:34
  12. C++入门_3运算符

    C笔记_3运算符算术运算符加减乘除赋值运算符比较运算符逻辑运算符算术运算符 加减乘除 - * / % 两小数不能取小数的余 a 前置 先加1&#xff0c;在表达式运算 a 后置 先表达式的运算&#xff0c;在加1 --a a--赋值运算符 赋值加等于 - 减等于 * 乘等于 / 除等于 % 模等于比…...

    2024/4/14 6:10:17
  13. L1-019 谁先倒 (15 分)

    划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为&#xff1a;每人口中喊出一个数字&#xff0c;同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和&#xff0c;谁就输了&#xff0c;输家罚一杯酒。两人同赢或两人同输则继续下一轮&…...

    2024/4/19 21:23:58
  14. Python基础:14_多进程

    from multiprocessing import Processdef func():for i in range(50000):print(子进程, i)if __name__ __main__:p Process(targetfunc)p.start()for i in range(50000):print(主进程, i)...

    2024/4/16 21:58:41
  15. 数仓理论(一)

    一&#xff1a;数仓管理者的主要任务和职责。 1.1&#xff1a;为什么数仓管理者要明白自己的职责&#xff1f; 数仓管理者手中有着非常重要的东西–数据。数仓管理者们被期望以能让资产最有用的方式将资产诠释并交付给组织的其余部分。 1.2 &#xff1a;数仓管理者该做什么&…...

    2024/4/14 6:10:42
  16. 不同硬盘读写速率区别

    机械硬盘、SATA协议和NVME协议固态的三块硬盘读写速度实测 - 知乎 (zhihu.com)...

    2024/4/23 13:16:10
  17. P1525 [NOIP2010 提高组] 关押罪犯 题解 | 种类并查集

    前言 并查集&#xff0c;想必大家并不陌生&#xff0c;她可以方便快捷地合并、查询两个集合。 例题&#xff1a;P1551 亲戚。 不过我们今天的重点不是普通并查集太简单了&#xff08;雾&#xff0c;而是并查集的一种变体&#xff0c;种类并查集。 Part1. 种类并查集 种类并…...

    2024/4/14 6:10:12
  18. 支小蜜智慧食堂刷脸就餐让学生不再刷卡吃饭

    在“互联网”的背景下&#xff0c;很多学校食堂就开始引入全新的食堂人脸识别就餐系统。而支小蜜智慧食堂刷脸就餐可以根据学生的实际用餐情况&#xff0c;打造智能选餐、刷脸结算、精准服务、智能营养报告的智慧食堂模式场景。让学生可以刷脸吃饭。 据了解&#xff0c;支小蜜…...

    2024/4/16 9:56:22
  19. java - 常用API、常用类

    常用API 什么是API&#xff1f; 应用程序编程接口&#xff1b;就是java已经写好的一些方法&#xff0c;可以直接拿过来用。 Object类的作用&#xff1a; 一个类要么默认继承了Object类&#xff0c;要么间接继承了Object类&#xff0c;Object类是java中的祖…...

    2024/4/19 9:15:58
  20. python flask 框架实现jwt用户登录 接口权限认证 案例

    环境&#xff1a;python3.6 模块&#xff1a;flask、jwt 目的&#xff1a;实现用于登录并返回token令牌&#xff0c;用于后续的接口权限验证。 前言介绍&#xff1a; jwt&#xff08;JSON Web Tokens&#xff09;&#xff0c;在用户认证当中常用的方式&#xff0c;在如今的前…...

    2024/4/20 5:19:14

最新文章

  1. ArgoCD集成部署到Kubernetes

    1&#xff1a;环境 kubernetes1.23.3ArgoCD2.3.3 2&#xff1a;ArgoCD介绍 Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. Argo CD是一个基于Kubernetes的声明式的GitOps工具。 那么&#xff0c;什么是GitOps呢&#xff1f; GitOps是以Git为基…...

    2024/4/25 6:28:27
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. PHP:获取时间戳,时间,以及相关转换

    一、获取当前时间戳 // 获取当前时间的时间戳&#xff08;秒级&#xff0c;11位&#xff09; $currentTimestampInSeconds time(); 二、秒级&#xff08;11位&#xff09;时间戳转换为毫秒级&#xff08;13位&#xff09;时间戳 乘以1000即可 // 转换为毫秒时间戳&#xf…...

    2024/4/25 2:10:53
  4. WKWebView的使用

    一、简介 在iOS中&#xff0c;WKWebView是WebKit框架提供的一个用于展示网页内容的控件&#xff0c;相比UIWebView有更好的性能和功能。 以下是在iOS中使用WKWebView的基本步骤&#xff1a; 1.1 导入WebKit框架 import WebKit1.2 创建WKWebView实例 let webView WKWebVie…...

    2024/4/23 6:10:52
  5. Redis精品案例解析:Redis实现持久化主要有两种方式

    Redis实现持久化主要有两种方式&#xff1a;RDB&#xff08;Redis DataBase&#xff09;和AOF&#xff08;Append Only File&#xff09;。这两种方式各有优缺点&#xff0c;适用于不同的使用场景。 1. RDB持久化 RDB持久化是通过创建一个二进制的dump文件来保存当前Redis数据…...

    2024/4/23 18:43:23
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/23 20:58:27
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/23 13:30:22
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/23 13:28:06
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/24 18:16:28
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/23 13:27:44
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/19 11:57:53
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/23 13:29:53
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/23 13:27:22
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/23 13:28:42
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/23 22:01:21
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/23 13:29:23
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/25 0:00:17
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/25 4:19:21
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/19 11:59:23
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/4/19 11:59:44
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/25 2:10:52
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/24 16:38:05
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/23 13:28:14
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/23 13:27:51
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/23 13:27:19
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57