组合模式

把一组相似的对象当作一个单一的对象。如:树形菜单

结构型-组合&外观&享元 - 图1

结构型-组合&外观&享元 - 图2

什么场景用到?

层级结构
部门组织结构
组合了别的对象还是组合模式吗? 可以说是的,只要用了组合都可以说是组合模式

外观模式

外观(Facade)模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式

结构型-组合&外观&享元 - 图3

  1. public class Edu {
  2. public void assignSchool(String name){
  3. System.out.println(name+",你的孩子明天去 硅谷大学附属幼儿园 报道......");
  4. }
  5. }
  6. public class Police {
  7. public void resgister(String name){
  8. System.out.println(name + "已办理落户");
  9. }
  10. }
  11. public class Social {
  12. public void handleSocial(String name){
  13. System.out.println(name+",你的社保关系已经转移....");
  14. }
  15. }
  1. public class WeiXinFacade {
  2. Police police = new Police();
  3. Edu edu = new Edu();
  4. Social social = new Social();
  5. /**
  6. * 封装起来只留一个方法
  7. * @param name
  8. */
  9. public void handleXxx(String name){
  10. police.resgister(name);
  11. edu.assignSchool(name);
  12. social.handleSocial(name);
  13. }
  14. public void resgister(String name){
  15. police.resgister(name);
  16. }
  17. public void assignSchool(String name){
  18. edu.assignSchool(name);
  19. }
  20. }
  1. /**
  2. * 需求:来回跑太麻烦,按照最少知道原则,我就想和一个部门进行交互。
  3. *
  4. *
  5. *
  6. */
  7. public class MainTest {
  8. public static void main(String[] args) {
  9. // Police police = new Police();
  10. // police.resgister("雷丰阳");
  11. //
  12. // Edu edu = new Edu();
  13. // edu.assignSchool("雷丰阳");
  14. //
  15. // Social social = new Social();
  16. // social.handleSocial("雷丰阳");
  17. WeiXinFacade facade = new WeiXinFacade();
  18. facade.handleXxx("雷丰阳");
  19. //
  20. // facade.resgister("");
  21. // facade.assignSchool("");
  22. }
  23. }

使用场景

什么场景使用?
去医院看病,可能要去挂号、门诊、划价、取药,让患者或患者家属觉得很复杂,如果有提供接待人员,只让接待人员来处理,就很方便。以此类比……
JAVA 的三层开发模式。
分布式系统的网关
Tomcat源码中的RequestFacade干什么的?
……

享元模式

在类的设计阶段要考虑的:

在享元模式中可以共享的相同内容称为内部状态(IntrinsicState),而那些需要外部环境来设置的不能共享的内容称为外部状态(Extrinsic State),由于区分了内部状态和外部状态,因此可以通过设置不同的外部状态使得相同的对象可以具有一些不同的特征,而相同的内部状态是可以共享的。
在享元模式中通常会出现工厂模式,需要创建一个享元工厂来负责维护一个享元池(Flyweight Pool)用于存储具有相同内部状态的享元对象。

享元模式包含如下角色:
Flyweight: 抽象享元类 Connection :需要有这个类来定义可共享和不可共享的状态
ConcreteFlyweight: 具体享元类 ConnectionImpl(user,pwd,url)
UnsharedConcreteFlyweight: 非共享具体享元类ConnectionImpl(每一个连接的状态state)
FlyweightFactory: 享元工厂类;简单工厂,产品就一个Connection

实例: 足疗店服务员

  1. /**
  2. * 可共享和不可共享状态
  3. */
  4. public abstract class AbstractWaitressFlyweight {
  5. boolean canService = true;//能否服务
  6. //正在服务。 享元的不可共享属性,留给外部进行改变的接口
  7. abstract void service();
  8. //服务完成。 享元的不可共享属性,留给外部进行改变的接口
  9. abstract void end();
  10. public boolean isCanService() {
  11. return canService;
  12. }
  13. }
  1. /**
  2. * 具体享元类
  3. */
  4. @AllArgsConstructor
  5. public class BeautifulWaitress extends AbstractWaitressFlyweight{
  6. String id;//工号
  7. String name;//名字
  8. int age;//年龄
  9. //以上是不变的
  10. @Override
  11. void service() {
  12. System.out.println("工号:"+id+";"+name+" "+age+" 正在为您服务...");
  13. //改变该对象外部状态
  14. this.canService = false;
  15. }
  16. @Override
  17. void end() {
  18. System.out.println("工号:"+id+";"+name+" "+age+" 服务结束...请给五星好评");
  19. //改变该对象外部状态
  20. this.canService = true;
  21. }
  22. }
  1. package com.atguigu.design.structural.flyweight;
  2. import java.util.*;
  3. /**
  4. * 足道店:这相当于享元工厂,因为都是针对服务员这一个对象,因此这里使用静态工厂。
  5. * 店里面很多服务员。
  6. *
  7. * 享元和原型
  8. * 1、享元返回的是这个本人。
  9. * 2、原型返回的是克隆人。
  10. *
  11. */
  12. public class ZuDao {
  13. private static Map<String,AbstractWaitressFlyweight> pool = new HashMap<>();
  14. //享元,池子中有对象
  15. static { //初始化池子中内容
  16. BeautifulWaitress waitress =
  17. new BeautifulWaitress("1111","张三",18);
  18. BeautifulWaitress waitress2 =
  19. new BeautifulWaitress("9527","李四",20);
  20. pool.put(waitress.id,waitress);
  21. pool.put(waitress2.id,waitress2);
  22. }
  23. public void addWaitress(AbstractWaitressFlyweight waitressFlyweight){
  24. pool.put(UUID.randomUUID().toString(),waitressFlyweight);
  25. }
  26. public static AbstractWaitressFlyweight getWaitress(String name){ //可以根据名字指定服务员
  27. AbstractWaitressFlyweight flyweight = pool.get(name);
  28. if(flyweight == null){//如果没传,则随机给一个可以服务的服务员
  29. for (AbstractWaitressFlyweight value : pool.values()) {
  30. //当前共享对象能否进行服务,需要在这里进行判断
  31. if(value.isCanService()){
  32. return value;
  33. }
  34. };
  35. return null;
  36. }
  37. return flyweight;
  38. }
  39. }
  1. public class MainTest {
  2. public static void main(String[] args) {
  3. //1、我
  4. AbstractWaitressFlyweight waitress = ZuDao.getWaitress("");
  5. waitress.service();
  6. System.out.println(waitress);
  7. //2、佟老师
  8. AbstractWaitressFlyweight waitress1 = ZuDao.getWaitress("");
  9. waitress1.service();
  10. System.out.println(waitress1);
  11. //服务完毕释放,改变其服务的外部状态
  12. waitress1.end();
  13. //3、刘佳林
  14. AbstractWaitressFlyweight waitress2 = ZuDao.getWaitress("");
  15. System.out.println(waitress2);
  16. }
  17. }

将一个类中可共享的属性抽离出来,并且提供方法可以改变这几个属性,外部通过调用方法对该属性值进行判断。

什么场景用到?

典型的代表:数据库连接池
所有的池化技术
享元和原型模式有什么区别?享元是预先准备好的对象进行复用,原型没法确定预先有哪些
……