5.外观模式
(1).概述
有些人可能超过股票,但是其实大部分人都不懂,这种没有足够了解证券知识的情况下做股票是很容易亏钱的,刚开始炒股肯定都会想,如果有个懂行的帮帮手,支付宝里面有很多基金,它将投资者分散的资金集中起来,交由专业的经理人进行管理,投资于股票、债卷、外汇等领域,而基金投资的收益归持有者所有,管理机构收取一定比列的托管管理费用
。
定义:
又名门面模式
,是一种通过多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一的接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性
。
迪米特法则的典型应用
(2).结构
外感模式包含以下主要角色:
- 外观角色: 为多个子系统对外提供一个共同的接口。
- 子系统角色: 实现系统的部分功能,客户可以通过外观角色访问它。
(3).案例
eg:智能家电控制
小明的爷爷已经60岁了,一个人在家生活;每次都需要打开灯、打开电视、打开空调;睡觉时关闭灯、关闭电视、关闭空调;操作起来都比较麻烦。所以小明给爷爷买了智能音箱,可以通过语言直接控制这些智能家电的开启和关闭。类图如下:
子类系统角色
package com.jsxs.structure.facade; /** * @Author Jsxs * @Date 2023/4/22 9:58 * @PackageName:com.jsxs.structure.facade * @ClassName: Light * @Description: TODO 子系统角色 * @Version 1.0 */ public class Light { public void on(){ System.out.println("开灯"); } public void off(){ System.out.println("关灯"); } }
package com.jsxs.structure.facade; /** * @Author Jsxs * @Date 2023/4/22 9:59 * @PackageName:com.jsxs.structure.facade * @ClassName: TV * @Description: TODO 子角色 * @Version 1.0 */ public class TV { public void on(){ System.out.println("开电视"); } public void off(){ System.out.println("关电视"); } }
package com.jsxs.structure.facade; /** * @Author Jsxs * @Date 2023/4/22 9:59 * @PackageName:com.jsxs.structure.facade * @ClassName: airContition * @Description: TODO 子类角色 * @Version 1.0 */ public class airContition { public void on(){ System.out.println("开灯空调"); } public void off(){ System.out.println("关空调"); } }
外观角色
package com.jsxs.structure.facade; /** * @Author Jsxs * @Date 2023/4/22 10:02 * @PackageName:com.jsxs.structure.facade * @ClassName: SmartFacade * @Description: TODO 外观角色 * @Version 1.0 */ public class SmartFacade { // 聚合 private Light light; private TV tv; private airContition airContition; // 实列化 public SmartFacade() { light=new Light(); tv=new TV(); airContition=new airContition(); } // 语音控制 public void say(String message){ if (message.contains("打开")){ on(); }else if (message.contains("关闭")){ off(); }else { System.out.println("我不知道你在说什么..."); } } // 一键打开 public void on(){ light.on(); tv.on(); airContition.on(); } // 一键关闭 public void off(){ light.off(); tv.off(); airContition.off(); } }
测试
package com.jsxs.structure.facade; /** * @Author Jsxs * @Date 2023/4/22 10:16 * @PackageName:com.jsxs.structure.facade * @ClassName: Client * @Description: TODO * @Version 1.0 */ public class Client { public static void main(String[] args) { SmartFacade smartFacade = new SmartFacade(); smartFacade.say("关闭"); smartFacade.say("打开"); } }
好处:
降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类
。- 对客户屏蔽了子系统的组件,减少了客户处理的对象数目,
并使得子系统使用起来更加容易
。
缺点:
- 不符合
开闭原则
,修改很麻烦。
(4).使用场景
- 对分层结构系统构建时,使用外观模式定义子系统中每层的入口可以简化子系统之间的依赖关系。
当一个复杂系统的子系统很多时,外观模式可以位系统设计一个简单的接口供外界访问
。当客户端与多个子系统之间存在很大的联系时
,引入外观模式可以将他们分离,从而提高自行的独立性和可移植性
。
(5).源码分析
使用tomcat作为web容器时,接受浏览器发送过来的而请求,tomcat会将请求信息封装成ServletRequest对象,但是大家想想ServletRequest是一个接口,它还有一个子接口HttpServletRequest,而我们都知道request对象肯定是一个ServletRequest对象的子实现类对象,到底是哪个类的对象呢,可以通过暑促和request对象,我们就会发现是一个名为RequestFacade的类的对象。
public class Personnel_visit_informationServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
为什么在这里使用外观模式?
定义RequestFacade
类,分别实现ServletRequest
,同时定义私有成员变量Request,
并且方法的实现调用Request
的实现。然后将RequestFacade上传位ServletRequest传给Servlet的service方法,这样即使在servlet中被下转为RequestFacade,也不能访问保护成员变量对象中的方法
。即用了Request,又能放置其中方法不合理的访问。
6.享元模式
(1).概述
定义:
运用共享技术
来有效的支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销,从而提高系统资源的利用率(共享单车)。
(2).结构
享元模式中存在以下两种状态:
- 内部状态: 既不会随着环境的改变而改变的可共享部分,
- 外部状态: 指随环境改变而改变的不可以共享的部分。享元模式实现就是区分应用中的这两种状态,并将外部状态外部化。
享元模式的主要角色:
- 抽象享元角色: 通常是一个
接口或者抽象类
,在抽象享元类中声明了具体享元对象的内部数据(内部状态
),同时也可以通过这些方法来设置外部数据(外部状态
) - 具体享元角色:
它实现了抽象享元类,称为享元对象
;在具体享元类中为内部状态提供了存储空间。通常我们可以结合单列模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。 - 非享元对象角色: 并不是所有的抽象享元类的子类都需要被共享,
不能被共享的子类可以设计为非共享具体享元类
;当需要一个非共享享元类的对象时可以直接通过实列化创建。 - 享元工厂角色:
负责创建和管理享元角色
。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象
。
(3).享元模式案列
eg: 俄罗斯方块
下面的图片就是总所周知的俄罗斯方块,如果在俄罗斯方块这个游戏中,每个不同的方块就是一个实列对象,这些对象就要占用很多的内存空间,下面利用享元模式进行实现。
类图:
代码如下:
俄罗斯方块有不同的形状,我们可以对这些形状向上抽象出AbstractBox,用来定义共性的属性和行为。
抽象享元角色
package com.jsxs.structure.flyweight; /** * @Author Jsxs * @Date 2023/4/22 14:47 * @PackageName:com.jsxs.structure.flyweight * @ClassName: AbstractBox * @Description: TODO 抽象享元角色 * @Version 1.0 */ public abstract class AbstractBox { // 获取图形的方法 public abstract String getShape(); // 显示图形及颜色 public void display(String color){ System.out.println("方块形状是: "+getShape()+" 颜色: "+color); } }
具体享元角色
package com.jsxs.structure.flyweight; /** * @Author Jsxs * @Date 2023/4/22 14:49 * @PackageName:com.jsxs.structure.flyweight * @ClassName: IBox * @Description: TODO 具体享元角色 * @Version 1.0 */ public class IBox extends AbstractBox{ @Override public String getShape() { return "I"; } }
package com.jsxs.structure.flyweight; /** * @Author Jsxs * @Date 2023/4/22 14:50 * @PackageName:com.jsxs.structure.flyweight * @ClassName: RBox * @Description: TODO * @Version 1.0 */ public class RBox extends AbstractBox{ @Override public String getShape() { return "R"; } }
package com.jsxs.structure.flyweight; /** * @Author Jsxs * @Date 2023/4/22 14:50 * @PackageName:com.jsxs.structure.flyweight * @ClassName: OBox * @Description: TODO * @Version 1.0 */ public class OBox extends AbstractBox{ @Override public String getShape() { return "O"; } }
享元工厂
package com.jsxs.structure.flyweight; import java.util.HashMap; /** * @Author Jsxs * @Date 2023/4/22 14:51 * @PackageName:com.jsxs.structure.flyweight * @ClassName: BoxFactory * @Description: TODO 享元工厂模式 * @Version 1.0 */ public class BoxFactory { private HashMap<String,AbstractBox> map; // 构造函数初始化且设置单列模式 private BoxFactory(){ map=new HashMap<String,AbstractBox>(); // 添加图像 map.put("I",new IBox()); map.put("R",new RBox()); map.put("O",new OBox()); } // 饿汉模式创建 private static BoxFactory factory=new BoxFactory(); // 提供一个方法获取该工厂类对象 public static BoxFactory getInstance(){ return factory; } // 根据名称获取图像对象 public AbstractBox getShape(String name){ return map.get(name); } }