Java设计模式

Yohann-study

Java设计模式笔记

设计模式

设计模式七大原则

单一职责原则

  • 一个类应该只负责一项职责。

接口隔离原则

  • 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应建立在最小接口上。

依赖倒转原则

  • 高层模块不应该依赖低层模块,两者都应该依赖其抽象。

  • 抽象不应该依赖细节。

  • 细节应该依赖抽象。

    依赖传递的三种方式
  • 接口传递

  • 构造器传递

  • setter传递

里氏替换原则

  • 子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法 。
  • 子类中可以增加自己特有的方法 。
  • 当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松 。

开闭原则

  • 对扩展开放(对提供方),对修改关闭(对使用方)。

迪米特原则

  • 最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。

合成复用原则

  • 尽量使用合成/聚合的方式,而不是使用继承。

创建型模式

单例模式

  • 采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得对象的实例方法(静态方法)。

  • 使用场景:需要频繁创建和销毁的对象,创建对象时耗时过多或者耗费资源过多。

  • 推荐使用:饿汉式、双重检查、静态内部类和枚举。

    饿汉式
    class HungrySingleton {
        /**
         * 自身实例为成员变量
         */
        private static final HungrySingleton INSTANCE = new HungrySingleton();
    
        /**
         * 私有构造
         */
        private HungrySingleton() {
        }
    
        /**
         * 对外暴露获取实例对象的方法
         *
         * @return 对象实例
         */
        public static HungrySingleton getInstance() {
            return INSTANCE;
        }
    }
    
    • 优点:在类装载时就完成了实例化,避免了线程同步问题。

    • 缺点:在类加载时就完成了实例,没有懒加载效果,可能造成内存浪费。

    饿汉式(静态代码块)
    class HungrySingleton2 {
        /**
         * 自身实例为成员变量
         */
        private static HungrySingleton2 instance;
    
        static {
            instance = new HungrySingleton2();
        }
    
        /**
         * 私有构造
         */
        private HungrySingleton2() {
        }
    
        /**
         * 对外暴露获取实例对象的方法
         *
         * @return 对象实例
         */
        public static HungrySingleton2 getInstance() {
            return instance;
        }
    }
    
    • 在静态代码块中实例化,优缺点与饿汉式一致。
    懒汉式
    class LazySingleton {
        /**
         * 自身实例为成员变量
         */
        private static LazySingleton instance;
    
        /**
         * 私有构造
         */
        private LazySingleton() {
        }
    
        /**
         * 对外暴露获取实例对象的方法
         *
         * @return 对象实例
         */
        public static LazySingleton getInstance() {
            //获取时实例为空才创建
            if (instance == null) {
                instance = new LazySingleton();
            }
    
            return instance;
        }
    }
    
    • 优点:有懒加载作用。

    • 缺点:线程不安全,实际开发不推荐使用。

    懒汉式(同步方法)
    class LazySingleton2 {
        /**
         * 自身实例为成员变量
         */
        private static LazySingleton2 instance;
    
        /**
         * 私有构造
         */
        private LazySingleton2() {
        }
    
        /**
         * 对外暴露获取实例对象的方法
         *
         * @return 对象实例
         */
        public synchronized static LazySingleton2 getInstance() {
            //获取时实例为空才创建
            if (instance == null) {
                instance = new LazySingleton2();
            }
    
            return instance;
        }
    }
    
    • 缺点:效率太低,不推荐使用。
    懒汉式(同步代码块)
    class LazySingleton3 {
        /**
         * 自身实例为成员变量
         */
        private static LazySingleton3 instance;
    
        /**
         * 私有构造
         */
        private LazySingleton3() {
        }
    
        /**
         * 对外暴露获取实例对象的方法
         *
         * @return 对象实例
         */
        public static LazySingleton3 getInstance() {
            //获取时实例为空才创建
            if (instance == null) {
                synchronized (LazySingleton3.class) {
                    instance = new LazySingleton3();
                }
            }
    
            return instance;
        }
    }
    
    • 缺点:效率太低,线程不安全,不推荐使用。
    双重检查
    class DoubleCheckSingleton {
        /**
         * 自身实例为成员变量
         */
        private static DoubleCheckSingleton instance;
    
        /**
         * 私有构造
         */
        private DoubleCheckSingleton() {
        }
    
        /**
         * 对外暴露获取实例对象的方法
         *
         * @return 对象实例
         */
        public static DoubleCheckSingleton getInstance() {
            //获取时实例为空才创建
            if (instance == null) {
    
                synchronized (DoubleCheckSingleton.class) {
                    //双重检查 保证创建一个实例
                    if (instance == null) {
                        instance = new DoubleCheckSingleton();
                    }
                }
            }
    
            return instance;
        }
    }
    
    • 优点:有懒加载,解决线程安全问题,兼顾效率,推荐使用。
    静态内部类
    class StaticInnerClassSingleton {
        /**
         * 私有构造
         */
        private StaticInnerClassSingleton() {
        }
    
        /**
         * 在静态内部类中实例化
         */
        private static class SingleInstance {
            private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
        }
    
        /**
         * 对外暴露获取实例对象的方法
         *
         * @return 对象实例
         */
        public static StaticInnerClassSingleton getInstance() {
            return SingleInstance.INSTANCE;
        }
    }
    
    • 优点:有懒加载,解决线程安全问题(类加载时线程安全)。
    枚举
    enum EnumSingleton {
        /**
         * 实例
         */
        INSTANCE;
    }
    
    • 优点:防止反序列化创建新对象,推荐使用。

工厂模式

  • 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

  • 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

    简单工厂模式
    • 定义:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。

    • 在简单工厂模式中用于被创建实例的方法通常为静态(static)方法,因此简单工厂模式又被成为静态工厂方法(Static Factory Method)。

      披萨🍕
       public abstract class Pizza {
            public abstract void prepare();
        
            public void bake() {
                System.out.println("bake");
            }
        
            public void cut() {
                System.out.println("cut");
            }
        
            public void box() {
                System.out.println("box");
            }
        }
        
        
        public class PepperPizza extends Pizza {
            @Override
            public void prepare() {
                System.out.println("pepper");
            }
        }
        
        
        public class GreekPizza extends Pizza{
            @Override
            public void prepare() {
                System.out.println("greek");
            }
        }
        
        
        public class CheesePizza extends Pizza {
            @Override
            public void prepare() {
                System.out.println("cheese");
            }
        }
      
      工厂
      public class SimpleFactory {
            public Pizza createPizza(String type) {
                Pizza pizza = null;
        
                if ("greek".equals(type)) {
                    pizza = new GreekPizza();
                } else if ("cheese".equals(type)) {
                    pizza = new CheesePizza();
                } else if ("pepper".equals(type)) {
                    pizza = new PepperPizza();
                }
        
                return pizza;
            }
        }
      
      消费
      public class OrderPizza {
            private final Scanner scanner = new Scanner(System.in);
            private SimpleFactory simpleFactory;
            private Pizza pizza;
        
            public OrderPizza(SimpleFactory simpleFactory) {
                this.setSimpleFactory(simpleFactory);
            }
        
            private void setSimpleFactory(SimpleFactory simpleFactory) {
                this.simpleFactory = simpleFactory;
        
                do {
                    String type = scanner.nextLine();
                    this.pizza = this.simpleFactory.createPizza(type);
        
                    if (pizza != null) {
                        pizza.prepare();
                        pizza.bake();
                        pizza.cut();
                        pizza.box();
                    }
                } while (true);
            }
        }
      
    工厂方法模式
    • 工厂方法模式是简单工厂的进一步抽象和推广,由于工厂方法模式具有多态性,工厂模式方法既保持了简单工厂的优点,同时又克服了它的缺点,简单工厂模式中的工厂类负责创建实例。 (相当于简单工厂模式的进一步抽象,类似二级目录)

      披萨🍕
      public class BeijingCheesePizza extends Pizza {
          @Override
          public void prepare() {
              System.out.println("北京奶酪披萨🍕");
          }
      }
      
      
      public class BeijingPepperPizza extends Pizza {
          @Override
          public void prepare() {
              System.out.println("北京胡椒披萨🍕");
          }
      }
      
      
      public class LondonCheesePizza extends Pizza {
          @Override
          public void prepare() {
              System.out.println("伦敦奶酪披萨🍕");
          }
      }
      
      
      public class LondonPepperPizza extends Pizza {
          @Override
          public void prepare() {
              System.out.println("伦敦胡椒披萨🍕");
          }
      }
      
      工厂
      public abstract class BaseFactory {
          private final Scanner scanner = new Scanner(System.in);
      
          abstract Pizza createPizza(String type);
      
          public BaseFactory() {
              do {
                  String type = scanner.nextLine();
                  Pizza pizza = createPizza(type);
      
                  if (pizza != null) {
                      pizza.prepare();
                      pizza.bake();
                      pizza.cut();
                      pizza.box();
                  }
              } while (true);
          }
      }
      
      
      public class BeijingFactory extends BaseFactory {
          @Override
          Pizza createPizza(String type) {
              Pizza pizza = null;
              if (type.equals("cheese")) {
                  pizza = new BeijingCheesePizza();
              } else if (type.equals("pepper")) {
                  pizza = new BeijingPepperPizza();
              }
      
              return pizza;
          }
      }
      
      
      public class LondonFactory extends BaseFactory {
          @Override
          Pizza createPizza(String type) {
              Pizza pizza = null;
              if (type.equals("cheese")) {
                  pizza = new LondonCheesePizza();
              } else if (type.equals("pepper")) {
                  pizza = new LondonPepperPizza();
              }
      
              return pizza;
          }
      }
      
    抽象工厂模式
    • 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

    • 在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

      抽象工厂
      public interface AbstractFactory {
          Pizza create(String type);
      }
      
      
      public class BeijingFactory implements AbstractFactory {
          @Override
          public Pizza create(String type) {
              Pizza pizza = null;
              if (type.equals("cheese")) {
                  pizza = new BeijingCheesePizza();
              } else if (type.equals("pepper")) {
                  pizza = new BeijingPepperPizza();
              }
      
              return pizza;
          }
      }
      
      
      public class LondonFactory implements AbstractFactory{
          @Override
          public Pizza create(String type) {
              Pizza pizza = null;
              if (type.equals("cheese")) {
                  pizza = new LondonCheesePizza();
              } else if (type.equals("pepper")) {
                  pizza = new LondonPepperPizza();
              }
      
              return pizza;
          }
      }
      
      消费
      public class OrderPizza {
          private final Scanner scanner = new Scanner(System.in);
          private AbstractFactory factory;
      
          public OrderPizza(AbstractFactory factory) {
              setFactory(factory);
          }
      
          private void setFactory(AbstractFactory factory) {
              do {
                  String type = scanner.nextLine();
                  Pizza pizza = factory.create(type);
      
                  if (pizza != null) {
                      pizza.prepare();
                      pizza.bake();
                      pizza.cut();
                      pizza.box();
                  }
              } while (true);
          }
      }
      

原型模式

  • 原型(Prototype)模式使用原型实例指定创建对象的种类,并且通过拷贝原型对象创建新的对象。

  • 缺点:需要对每一个类添加克隆方法。

    克隆羊
    • 直接按照对象的属性克隆一个新的对象。
    public class Sheep implements Cloneable {
        private String name;
        private String color;
    
        public Sheep(String name, String color) {
            this.name = name;
            this.color = color;
        }
        
        @Override
        public String toString() {
            return "Sheep{" +
                    "name='" + name + '\'' +
                    ", color='" + color + '\'' +
                    '}';
        }
    
        /**
         * 实现Cloneable接口
         * 重写克隆方法
         */
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    
    public class Client {
        public static void main(String[] args) throws CloneNotSupportedException {
            Sheep sheep = new Sheep("pony", "yellow");
            Sheep clone1 = (Sheep) sheep.clone();
            Sheep clone2 = (Sheep) sheep.clone();
    
            /*
            clone1:Sheep{name='pony', color='yellow'}
            clone2:Sheep{name='pony', color='yellow'}
            false
             */
            System.out.println("clone1:" + clone1);
            System.out.println("clone2:" + clone2);
            System.out.println(clone1.equals(clone2));
        }
    }
    
    浅拷贝
    • 对于基本数据类型直接复制,对于引用数据类型直接属性对象的地址值。
    public class Sheep2 extends Sheep {
        //添加引用类型属性
        Sheep friend;
        
        public Sheep2(String name, String color) {
            super(name, color);
        }
    
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    
    public class Client {
        public static void main(String[] args) throws CloneNotSupportedException {
            Sheep2 sheep2 = new Sheep2("pony", "yellow");
            sheep2.friend = new Sheep("jack", "green");
    
            Sheep2 clone1 = (Sheep2) sheep2.clone();
            Sheep2 clone2 = (Sheep2) sheep2.clone();
    
            //false
            System.out.println(clone1 == clone2);
            //true
            System.out.println(clone1.friend == clone2.friend);
        }
    }
    
    深拷贝
    • 对引用属性单独拷贝
    public class DeepCloneableTarget implements Serializable, Cloneable {
        private static final Long serialVersionUID = 1L;
    
        private String cloneName;
        private String cloneClass;
    
        public DeepCloneableTarget(String cloneName, String cloneClass) {
            this.cloneName = cloneName;
            this.cloneClass = cloneClass;
        }
    
        @Override
        protected DeepCloneableTarget clone() throws CloneNotSupportedException {
            return (DeepCloneableTarget)super.clone();
        }
    }
    
    
    public class DeepPrototype implements Serializable, Cloneable {
        private static final Long serialVersionUID = 1L;
    
        String name;
        DeepCloneableTarget target;
    
        /**
         * 对引用数据类型进行单独处理
         */
        @Override
        protected DeepPrototype clone() throws CloneNotSupportedException {
            DeepPrototype deep = (DeepPrototype) super.clone();
            
            deep.target = (deep.target.clone());
    
            return deep;
        }
    }
    
    
    public class Client {
        public static void main(String[] args) throws CloneNotSupportedException {
            DeepPrototype deepPrototype = new DeepPrototype();
            deepPrototype.name = "clone-test";
            deepPrototype.target = new DeepCloneableTarget("clone-name", "clone-class");
    
            DeepPrototype clone1 = deepPrototype.clone();
            DeepPrototype clone2 = deepPrototype.clone();
    
            //false
            System.out.println(clone1 == clone2);
            //false
            System.out.println(clone1.target == clone2.target);
        }
    }
    
    • 序列化深拷贝
    public class DeepPrototype implements Serializable {
        private static final Long serialVersionUID = 1L;
    
        String name;
        DeepCloneableTarget target;
    
        /**
         * 通过序列化进行深拷贝
         */
        public DeepPrototype deepClone() {
            ByteArrayOutputStream byteArrayOutputStream = null;
            ObjectOutputStream objectOutputStream = null;
            ByteArrayInputStream byteArrayInputStream = null;
            ObjectInputStream objectInputStream = null;
    
            try {
                //序列化
                byteArrayOutputStream = new ByteArrayOutputStream();
                objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
    
                //当前对象以对象流输出
                objectOutputStream.writeObject(this);
    
                //反序列
                byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
                objectInputStream = new ObjectInputStream(byteArrayInputStream);
    
                //转成对象
                return (DeepPrototype) objectInputStream.readObject();
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (objectInputStream != null) {
                        objectInputStream.close();
                    }
                    if (byteArrayInputStream != null) {
                        byteArrayInputStream.close();
                    }
                    if (objectOutputStream != null) {
                        objectOutputStream.close();
                    }
                    if (byteArrayOutputStream != null) {
                        byteArrayOutputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    }
    

建造者模式

  • 建造者(生成器)模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

  • 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

    建造者
    public abstract class HouseBuilder {
        protected House house = new House();
    
        /**
         * 地基
         */
        public abstract void buildBasic();
    
        /**
         * 砌墙
         */
        public abstract void buildWalls();
    
        /**
         * 封顶
         */
        public abstract void roofed();
    }
    
    房子
    public class House {
        private String basic;
        private String wall;
        private String roof;
    
        public String getBasic() {
            return basic;
        }
    
        public void setBasic(String basic) {
            this.basic = basic;
        }
    
        public String getWall() {
            return wall;
        }
    
        public void setWall(String wall) {
            this.wall = wall;
        }
    
        public String getRoof() {
            return roof;
        }
    
        public void setRoof(String roof) {
            this.roof = roof;
        }
    
        @Override
        public String toString() {
            return "House{" +
                    "basic='" + basic + '\'' +
                    ", wall='" + wall + '\'' +
                    ", roof='" + roof + '\'' +
                    '}';
        }
    }
    
    产品
    public class SmallHouse extends HouseBuilder {
        @Override
        public void buildBasic() {
            house.setBasic("small-basic");
        }
    
        @Override
        public void buildWalls() {
            house.setWall("small-walls");
        }
    
        @Override
        public void roofed() {
            house.setRoof("small-roofed");
        }
    }
    
    
    public class BigHouse extends HouseBuilder {
        @Override
        public void buildBasic() {
            house.setBasic("big-basic");
        }
    
        @Override
        public void buildWalls() {
            house.setWall("big-walls");
        }
    
        @Override
        public void roofed() {
            house.setRoof("big-roofed");
        }
    }
    
    指挥者
    public class HouseDirector {
        HouseBuilder houseBuilder = null;
    
        public HouseDirector(HouseBuilder houseBuilder) {
            this.houseBuilder = houseBuilder;
        }
    
        public void setHouseBuilder(HouseBuilder houseBuilder) {
            this.houseBuilder = houseBuilder;
        }
    
        /**
         * 执行制作流程
         *
         * @return 返回房子
         */
        public House constructHouse() {
            houseBuilder.buildBasic();
            houseBuilder.buildWalls();
            houseBuilder.roofed();
    
            return houseBuilder.house;
        }
    }
    
    消费者
    public class HouseConsumer {
        public static void main(String[] args) {
            SmallHouse smallHouseProvider = new SmallHouse();
            House smallHouse = new HouseDirector(smallHouseProvider).constructHouse();
            
            //House{basic='small-basic', wall='small-walls', roof='small-roofed'}
            System.out.println(smallHouse);
    
            BigHouse bigHouseProvider = new BigHouse();
            House bigHouse = new HouseDirector(bigHouseProvider).constructHouse();
            
            //House{basic='big-basic', wall='big-walls', roof='big-roofed'}
            System.out.println(bigHouse);
        }
    

}


- 建造者 = 建造的基本步骤
- 提供者 = 建造的方案
- 指挥者 = 执行提供者的建造方案



## 结构性模式

### 适配器模式

- 适配器模式`(Adapter Pattern)`是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

- 这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。

#### 类适配器

-  Adapter 类既继承被适配类,也实现了 Target 接口(因为 Java 不支持多继承,所以这样来实现),在 Client 类中我们可以根据需要选择并创建任一种符合需求的子类,来实现具体功能。 

  ##### 被适配者

  ```java
  public class Voltage220V {
          public int output220V() {
            return 220;
          }
  }
  ```
  
  ##### 适配者
  
  ```java
  public interface Voltage5V {
      int output5V();
  }
  ```
  
  ##### 适配器
  
  ```java
  public class VoltageAdapter extends Voltage220V implements Voltage5V{
      @Override
      public int output5V() {
          int source = output220V();
  
          //进行适配
          return source / 44;
      }
  }
  ```

#### 对象适配器

- 被适配者由继承改为聚合。

  ```java
  public class ObjectAdapter implements Voltage5V {
      private Voltage220V voltage220V;
  
      public ObjectAdapter(Voltage220V voltage220V) {
          this.voltage220V = voltage220V;
      }
  
      @Override
      public int output5V() {
          int source = this.voltage220V.output220V();
  
          //进行适配
          return source / 44;
      }
  }
  ```

  

#### 接口适配器`(缺省适配器)`

- 当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。

- 适用于一个接口不想使用其所有的方法的情况。

  ##### 上层接口

  ```java
  public interface Interface {
      void method1();
  
      void method2();
  
      void method3();
  
      void method4();
  }
  ```

  ##### 缺省适配器

  ```java
  public abstract class DefaultAdapter implements Interface {
      @Override
      public void method1() {
  
      }
  
      @Override
      public void method2() {
  
      }
  
      @Override
      public void method3() {
  
      }
  
      @Override
      public void method4() {
  
      }
  }
  ```

  ##### 客户端

  ```java
  public class Client {
      public static void main(String[] args) {
          //用匿名内部类使用缺省适配器
          DefaultAdapter adapter = new DefaultAdapter() {
              //对需要使用的方法进行适配
              @Override
              public void method1() {
                  System.out.println("method1");
              }
          };
  
          adapter.method1();
      }
  }
  ```




### 桥接模式

- 桥接`(Bridge)`模式是指:将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。

- 桥接模式基于类最小设计原则,通过使用封装、聚合及继承等行为让不同的类承担不同的职责。

#### 手机品牌

```java
public interface Brand {
    void call();
    void open();
    void close();
}


public class iPhone implements Brand {
    @Override
    public void call() {
        System.out.println("iPhone call");
    }

    @Override
    public void open() {
        System.out.println("iPhone open");
    }

    @Override
    public void close() {
        System.out.println("iPhone close");
    }
}


public class ViVo implements Brand {
    @Override
    public void call() {
        System.out.println("ViVo call");
    }

    @Override
    public void open() {
        System.out.println("ViVo open");
    }

    @Override
    public void close() {
        System.out.println("ViVo close");
    }
}
手机样式
public abstract class Phone {
    /**
     * 组合品牌
     */
    private Brand brand;

    public Phone(Brand brand) {
        this.brand = brand;
    }

    public void call() {
        brand.call();
    }

    public void open() {
        brand.open();
    }

    public void close() {
        brand.close();
    }
}


public class FoldedPhone extends Phone {
    public FoldedPhone(Brand brand) {
        super(brand);
    }

    @Override
    public void call() {
        System.out.print("Folded-");
        super.call();
    }

    @Override
    public void open() {
        System.out.print("Folded-");
        super.open();
    }

    @Override
    public void close() {
        System.out.print("Folded-");
        super.close();
    }
}


public class UprightPhone extends Phone{
    public UprightPhone(Brand brand) {
        super(brand);
    }

    @Override
    public void call() {
        System.out.print("Upright-");
        super.call();
    }

    @Override
    public void open() {
        System.out.print("Upright-");
        super.open();
    }

    @Override
    public void close() {
        System.out.print("Upright-");
        super.close();
    }
}
客户端
public class Client {
    public static void main(String[] args) {
        FoldedPhone iphone = new FoldedPhone(new iPhone());

        /*
        Folded-iPhone open
        Folded-iPhone call
        Folded-iPhone close
         */
        iphone.open();
        iphone.call();
        iphone.close();

        FoldedPhone vivo = new FoldedPhone(new ViVo());

        /*
        Folded-ViVo open
        Folded-ViVo call
        Folded-ViVo close
         */
        vivo.open();
        vivo.call();
        vivo.close();
    }
}

装饰者模式

  • 装饰者模式:动态地将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)

    咖啡
    public abstract class Drink {
        private String description;
        private Float price = 0.0F;
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public Float getPrice() {
            return price;
        }
    
        public void setPrice(Float price) {
            this.price = price;
        }
    
        public abstract Float cost();
    }
    
    
    public class Coffee extends Drink {
        @Override
        public Float cost() {
            return super.getPrice();
        }
    }
    
    
    public class LongBlackCoffee extends Coffee {
        public LongBlackCoffee() {
            setDescription("LongBlackCoffee");
            setPrice(7.99F);
        }
    }
    
    
    public class ShortBlackCoffee extends Coffee {
        public ShortBlackCoffee() {
            setDescription("ShortBlackCoffee");
            setPrice(6.99F);
        }
    }
    
    调料(装饰者)
    public class Decorator extends Drink {
        private Drink drink;
    
        public Decorator(Drink drink) {
            this.drink = drink;
        }
    
        @Override
        public Float cost() {
            return super.getPrice() + drink.cost();
        }
    
        @Override
        public String getDescription() {
            return drink.getDescription() + " && " + super.getDescription() + " " + super.getPrice();
        }
    }
    
    
    public class Chocolate extends Decorator {
        public Chocolate(Drink drink) {
            super(drink);
            setDescription("Chocolate");
            setPrice(1.29F);
        }
    }
    
    
    public class Milk extends Decorator {
        public Milk(Drink drink) {
            super(drink);
            setDescription("Milk");
            setPrice(0.99F);
        }
    }
    
    咖啡屋
    public class CoffeeBar {
        public static void main(String[] args) {
            //创建一个咖啡
            Drink longBlack = new LongBlackCoffee();
            //添加牛奶
            Milk milkLongBlack = new Milk(longBlack);
            //添加巧克力
            Chocolate chocolateMilkLongBlack = new Chocolate(milkLongBlack);
    
            //LongBlackCoffee && Milk 0.99 && Chocolate 1.29 = 10.2699995
            System.out.println(chocolateMilkLongBlack.getDescription() + " = " + chocolateMilkLongBlack.cost());
        }
    }
    

组合模式

  • 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

  • 这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

  • 我们通过下面的实例来演示组合模式的用法。实例演示了一个组织中员工的层次结构。

    组合体抽象
    public abstract class OrganizationComponent {
        private String name;
        private String description;
    
        public OrganizationComponent(String name, String description) {
            this.name = name;
            this.description = description;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        protected void add(OrganizationComponent component) {
            throw new UnsupportedOperationException();
        }
    
        protected void remove(OrganizationComponent component) {
            throw new UnsupportedOperationException();
        }
    
        protected abstract void print();
    }
    
    组合内容
    public class University extends OrganizationComponent {
        private List<OrganizationComponent> components = new ArrayList<>();
    
        public University(String name, String description) {
            super(name, description);
        }
    
        @Override
        protected void add(OrganizationComponent component) {
            components.add(component);
        }
    
        @Override
        protected void remove(OrganizationComponent component) {
            components.remove(component);
        }
    
        @Override
        protected void print() {
            System.out.println("<====== " + getName() + " ======>");
            System.out.println();
            for (OrganizationComponent component : components) {
                component.print();
            }
            System.out.println();
        }
    }
    
    
    public class College extends OrganizationComponent {
        private List<OrganizationComponent> components = new ArrayList<>();
    
        public College(String name, String description) {
            super(name, description);
        }
    
        @Override
        protected void add(OrganizationComponent component) {
            components.add(component);
        }
    
        @Override
        protected void remove(OrganizationComponent component) {
            components.remove(component);
        }
    
        @Override
        protected void print() {
            System.out.println("<====== " + getName() + " ======>");
            for (OrganizationComponent component : components) {
                component.print();
            }
            System.out.println();
        }
    }
    
    
    public class Department extends OrganizationComponent {
        public Department(String name, String description) {
            super(name, description);
        }
    
        @Override
        protected void print() {
            System.out.println("<====== " + getName() + " ======>");
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            OrganizationComponent university = new University("清华大学", "五道口职业技术学院");
            OrganizationComponent college1 = new College("计算机学院", "秃头学院");
            OrganizationComponent college2 = new College("信息学院", "信息学院");
            university.add(college1);
            university.add(college2);
    
            OrganizationComponent department1 = new Department("软件工程", "IT民工");
            OrganizationComponent department2 = new Department("网络工程", "网线管理员");
            OrganizationComponent department3 = new Department("信息工程", "信息工程");
            OrganizationComponent department4 = new Department("通讯工程", "通讯工程");
            college1.add(department1);
            college1.add(department2);
            college2.add(department3);
            college2.add(department4);
    
            /*
            <====== 清华大学 ======>
    
            <====== 计算机学院 ======>
            <====== 软件工程 ======>
            <====== 网络工程 ======>
    
            <====== 信息学院 ======>
            <====== 信息工程 ======>
            <====== 通讯工程 ======>
             */
            university.print();
        }
    }
    

外观模式

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

  • 该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

    部件
    public class DVDPlayer {
        private static DVDPlayer ourInstance = new DVDPlayer();
    
        public static DVDPlayer getInstance() {
            return ourInstance;
        }
    
        private DVDPlayer() {
        }
    
        public void on() {
            System.out.println("DVD ON");
        }
    
        public void off() {
            System.out.println("DVD OFF");
        }
    
        public void play() {
            System.out.println("DVD IS PLAYING");
        }
    
        public void pause() {
            System.out.println("DVD IS pause");
        }
    }
    
    
    public class Popcorn {
        private static Popcorn ourInstance = new Popcorn();
    
        public static Popcorn getInstance() {
            return ourInstance;
        }
    
        private Popcorn() {
        }
    
        public void on() {
            System.out.println("Popcorn ON");
        }
    
        public void off() {
            System.out.println("Popcorn OFF");
        }
    
        public void pop() {
            System.out.println("Popcorn IS POPING");
        }
    }
    
    
    
    public class Projector {
        private static Projector ourInstance = new Projector();
    
        public static Projector getInstance() {
            return ourInstance;
        }
    
        private Projector() {
        }
    
        public void on() {
            System.out.println("Projector ON");
        }
    
        public void off() {
            System.out.println("Projector OFF");
        }
    
        public void focus() {
            System.out.println("Projector IS focusing");
        }
    }
    
    
    
    public class Screen {
        private static Screen ourInstance = new Screen();
    
        public static Screen getInstance() {
            return ourInstance;
        }
    
        private Screen() {
        }
    
        public void up() {
            System.out.println("Screen up");
        }
    
        public void down() {
            System.out.println("Screen down");
        }
    }
    
    
    public class Stereo {
        private static Stereo ourInstance = new Stereo();
    
        public static Stereo getInstance() {
            return ourInstance;
        }
    
        private Stereo() {
        }
    
        public void on() {
            System.out.println("Stereo ON");
        }
    
        public void off() {
            System.out.println("Stereo OFF");
        }
    
        public void up() {
            System.out.println("Stereo up");
        }
    
        public void down() {
            System.out.println("Stereo down");
        }
    }
    
    
    public class TheaterLight {
        private static TheaterLight ourInstance = new TheaterLight();
    
        public static TheaterLight getInstance() {
            return ourInstance;
        }
    
        private TheaterLight() {
        }
    
        public void on() {
            System.out.println("TheaterLight ON");
        }
    
        public void off() {
            System.out.println("TheaterLight OFF");
        }
    
        public void dim() {
            System.out.println("TheaterLight dim");
        }
    
        public void bright() {
            System.out.println("TheaterLight bright");
        }
    }
    
    外观
    public class HomeTheaterFacade {
        private TheaterLight light;
        private DVDPlayer player;
        private Popcorn popcorn;
        private Projector projector;
        private Screen screen;
        private Stereo stereo;
    
        public HomeTheaterFacade() {
            this.light = TheaterLight.getInstance();
            this.player = DVDPlayer.getInstance();
            this.popcorn = Popcorn.getInstance();
            this.projector = Projector.getInstance();
            this.screen = Screen.getInstance();
            this.stereo = Stereo.getInstance();
        }
    
        public void ready(){
            popcorn.on();
            popcorn.pop();
            screen.down();
            projector.on();
            stereo.on();
            player.on();
            light.dim();
        }
    
        public void play(){
            player.play();
        }
    
        public void pause(){
            player.pause();
        }
    
        public void end(){
            popcorn.off();
            light.bright();
            screen.up();
            projector.off();
            stereo.off();
            player.off();
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            HomeTheaterFacade facade = new HomeTheaterFacade();
    
            /*
            Popcorn ON
            Popcorn IS POPING
            Screen down
            Projector ON
            Stereo ON
            DVD ON
            TheaterLight dim
            ===================================
            DVD IS PLAYING
            ===================================
            DVD IS pause
            ===================================
            Popcorn OFF
            TheaterLight bright
            Screen up
            Projector OFF
            Stereo OFF
            DVD OFF
             */
            facade.ready();
            System.out.println("===================================");
            facade.play();
            System.out.println("===================================");
            facade.pause();
            System.out.println("===================================");
            facade.end();
        }
    }
    

享元模式

  • 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。

  • 享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

    网站
    public abstract class Website {
        abstract void use(User user);
    }
    
    
    public class ConcreteWebsite extends Website {
        private String type = "";
    
        public ConcreteWebsite(String type) {
            this.type = type;
        }
    
        @Override
        void use(User user) {
            System.out.println(user.getName() + " use " + type + " website");
        }
    }
    
    网站工厂
    public class WebsiteFactory {
        private HashMap<String, ConcreteWebsite> pool = new HashMap<>();
    
        public Website getWebsiteCategory(String type) {
            if (!pool.containsKey(type)) {
                pool.put(type, new ConcreteWebsite(type));
            }
    
            return (Website) pool.get(type);
        }
    
        public int getWebsiteSize() {
            return pool.size();
        }
    }
    
    用户
    public class User {
        private String name;
    
        public String getName() {
            return name;
        }
    
        public User setName(String name) {
            this.name = name;
            return this;
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            WebsiteFactory factory = new WebsiteFactory();
            Website website1 = factory.getWebsiteCategory("news");
            Website website2 = factory.getWebsiteCategory("news");
            Website website3 = factory.getWebsiteCategory("blog");
    
            //true
            System.out.println(website1 == website2);
    
            //pony use news website
            website1.use(new User().setName("pony"));
    
            //2
            System.out.println(factory.getWebsiteSize());
        }
    }
    

代理模式

  • 代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

  • 被代理的可以是远程对象、创建花销大的对象或需要安全控制的对象。

  • 代理模式主要有两种:静态代理、动态代理。

  • 动态代理包括JDK代理(接口代理)和Cglib代理(子类代理)。

    静态代理
    • 由程序员创建或工具生成代理类的源码,再编译代理类。

    • 在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。

      抽象接口
      public interface ITeacherDao {
          void teach();
      }
      
      接口实现
      public class TeacherDao implements ITeacherDao {
          @Override
          public void teach() {
              System.out.println("teaching");
          }
      }
      
      接口代理
      public class TeacherDaoProxy implements ITeacherDao {
          private ITeacherDao target;
      
          public TeacherDaoProxy(ITeacherDao target) {
              this.target = target;
          }
      
          @Override
          public void teach() {
              System.out.println("proxy start...");
              target.teach();
              System.out.println("proxy end...");
          }
      }
      
      客户端
      public class Client {
          public static void main(String[] args) {
              TeacherDaoProxy proxy = new TeacherDaoProxy(new TeacherDao());
      
              /*
              proxy start...
              teaching
              proxy end...
               */
              proxy.teach();
          }
      }
      
    JDK代理
    • 在程序运行时,通过反射机制动态创建而成。
    代理工厂
    public class ProxyFactory {
        private Object target;
    
        public ProxyFactory(Object object) {
            this.target = object;
        }
    
        public Object getProxyInstance() {
            /*
             * newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
             * loader目标对象的类加载器
             * interfaces目标对象的接口类型
             * h 事件处理
             */
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> {
                System.out.println("jdk proxy start");
                Object invoke = method.invoke(target, args);
                System.out.println("jdk proxy end");
                return invoke;
            });
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            ITeacherDao target = new TeacherDao();
            ITeacherDao instance = (ITeacherDao) new ProxyFactory(target).getProxyInstance();
    
            /*
            jdk proxy start
            jdk proxy end
            com.yohann.designPattern.proxy.staticproxy.TeacherDao@568db2f2
             */
            System.out.println(instance);
    
            /*
            class com.sun.proxy.$Proxy0
             */
            System.out.println(instance.getClass());
    
            /*
            jdk proxy start
            teaching
            jdk proxy end
             */
            instance.teach();
        }
    }
    
    Cglib代理
    • Cglib代理,也叫做子类代理。cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
    代理工厂
    public class ProxyFactory implements MethodInterceptor {
        private Object target;
    
        public ProxyFactory(Object object) {
            this.target = object;
        }
    
        public Object getProxyInstance() {
            //创建增强工具类
            Enhancer enhancer = new Enhancer();
    
            //设置父类
            enhancer.setSuperclass(target.getClass());
    
            //设置回调函数
            enhancer.setCallback(this);
    
            //创建子类对象
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("cglib proxy start");
            Object invoke = method.invoke(target, objects);
            System.out.println("cglib proxy end");
            return invoke;
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            TeacherDao target = new TeacherDao();
            TeacherDao instance = (TeacherDao) new ProxyFactory(target).getProxyInstance();
    
            /*
            cglib proxy start
            cglib proxy end
            com.yohann.designPattern.proxy.staticproxy.TeacherDao@1cf4f579
             */
            System.out.println(instance);
    
            /*
            class com.yohann.designPattern.proxy.staticproxy.TeacherDao$$EnhancerByCGLIB$$a2280d08
             */
            System.out.println(instance.getClass());
    
            /*
            cglib proxy start
            teaching
            cglib proxy end
             */
            instance.teach();
        }
    }
    

行为型模式

模板模式

  • 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。

  • 它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行

    豆浆抽象
    public abstract class SoyMilk {
        //制作方法(模板)
        final void make() {
            select();
            addCondiments();
            soak();
            beak();
        }
    
        private void select() {
            System.out.println("选豆");
        }
    
        abstract void addCondiments();
    
        private void soak() {
            System.out.println("浸泡");
        }
    
        private void beak() {
            System.out.println("打豆");
        }
    }
    
    豆浆实现
    public class PeanutSoyMilk extends SoyMilk {
        @Override
        void addCondiments() {
            System.out.println("加入花生🥜");
        }
    }
    
    
    public class RedBeanSoyMilk extends SoyMilk {
        @Override
        void addCondiments() {
            System.out.println("加入红豆");
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            /*
            选豆
            加入花生🥜
            浸泡
            打豆
             */
            new PeanutSoyMilk().make();
    
            /*
            选豆
            加入红豆
            浸泡
            打豆
             */
            new RedBeanSoyMilk().make();
        }
    }
    

命令模式

  • 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志。以及支持可撤销的操作。

    命令

public interface Command {
void execute();

  void undo();

}

public class NoCommand implements Command {
@Override
public void execute() {

  }

  @Override
  public void undo() {

  }

}

public class LightOnCommand implements Command {
private LightReceiver lightReceiver;

  public LightOnCommand(LightReceiver lightReceiver) {
      this.lightReceiver = lightReceiver;
  }

  @Override
  public void execute() {
      lightReceiver.on();
  }

  @Override
  public void undo() {
      lightReceiver.off();
  }

}

public class LightOffCommand implements Command {
private LightReceiver lightReceiver;

  public LightOffCommand(LightReceiver lightReceiver) {
      this.lightReceiver = lightReceiver;
  }

  @Override
  public void execute() {
      lightReceiver.off();
  }

  @Override
  public void undo() {
      lightReceiver.on();
  }

}




#### 接收者

```java
public class LightReceiver {
    public void on() {
        System.out.println("light on");
    }

    public void off() {
        System.out.println("light off");
    }
}
遥控器
public class RemoteController {
    private Command[] onCommand;
    private Command[] offCommand;
    private Command undoCommand;

    public RemoteController() {
        onCommand = new Command[5];
        offCommand = new Command[5];
        for (int i = 0; i < 5; i++) {
            onCommand[i] = new NoCommand();
            offCommand[i] = new NoCommand();
        }
    }

    public void setCommand(int no, Command onCommand, Command offCommand) {
        this.onCommand[no] = onCommand;
        this.offCommand[no] = offCommand;
    }

    public void onButtonPushed(int no) {
        onCommand[no].execute();
        undoCommand = onCommand[no];
    }

    public void offButtonPushed(int no) {
        offCommand[no].execute();
        undoCommand = offCommand[no];
    }

    public void undoButtonPushed(int no) {
        undoCommand.undo();
    }
}
客户端
public class Client {
    public static void main(String[] args) {
        LightReceiver receiver = new LightReceiver();
        LightOnCommand onCommand = new LightOnCommand(receiver);
        LightOffCommand offCommand = new LightOffCommand(receiver);
        RemoteController controller = new RemoteController();

        controller.setCommand(0, onCommand, offCommand);

        //light on
        controller.onButtonPushed(0);

        //light off
        controller.offButtonPushed(0);

        //light on
        controller.undoButtonPushed(0);
    }
}

访问者模式

  • 在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。

  • 通过这种方式,元素的执行算法可以随着访问者改变而改变。

    状态
    public abstract class Action {
        public abstract void getManResult(Man man);
    
        public abstract void getWomanResult(Woman woman);
    }
    
    
    public class Success extends Action {
        @Override
        public void getManResult(Man man) {
            System.out.println("man:success");
        }
    
        @Override
        public void getWomanResult(Woman woman) {
            System.out.println("woman:success");
        }
    }
    
    
    public class Fail extends Action {
        @Override
        public void getManResult(Man man) {
            System.out.println("man:fail");
        }
    
        @Override
        public void getWomanResult(Woman woman) {
            System.out.println("woman:fail");
        }
    }
    
    
    public class Wait extends Action {
        @Override
        public void getManResult(Man man) {
            System.out.println("man:wait");
        }
    
        @Override
        public void getWomanResult(Woman woman) {
            System.out.println("woman:wait");
        }
    }
    
    public abstract class Person {
        abstract void accept(Action action);
    }
    
    
    public class Man extends Person {
        @Override
        void accept(Action action) {
            action.getManResult(this);
        }
    }
    
    
    public class Woman extends Person {
        @Override
        void accept(Action action) {
            action.getWomanResult(this);
        }
    }
    
    构造
    public class ObjectStructure {
        private List<Person> people = new LinkedList<>();
    
        public void attach(Person person) {
            people.add(person);
        }
    
        public void detach(Person person) {
            people.remove(person);
        }
    
        public void display(Action action) {
            for (Person person : people) {
                person.accept(action);
            }
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            ObjectStructure structure = new ObjectStructure();
            structure.attach(new Man());
            structure.attach(new Woman());
    
            Action success = new Success();
            Action fail = new Fail();
    
            /*
            man:success
            woman:success
             */
            structure.display(success);
    
            /*
            man:fail
            woman:fail
             */
            structure.display(fail);
    
            /*
            man:wait
            woman:wait
             */
            Action wait = new Wait();
            structure.display(wait);
        }
    }
    

迭代器模式

  • 迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
学院
public interface College {
    String getName();

    void addDepartment(String name, String description);

    Iterator createIterator();
}


public class Department {
    private String name;
    private String description;

    public Department(String name, String description) {
        this.name = name;
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return description;
    }
}


public class ComputerCollege implements College {
    private Department[] departments;
    private int size = 0;

    public ComputerCollege() {
        this.departments = new Department[5];
        addDepartment("Java", "Java");
        addDepartment("PHP", "PHP");
        addDepartment("C", "C");
        addDepartment("C++", "C++");
        addDepartment("C#", "C#");
    }

    @Override
    public String getName() {
        return "computer";
    }

    @Override
    public void addDepartment(String name, String description) {
        Department department = new Department(name, description);
        departments[size] = department;
        size++;
    }

    @Override
    public Iterator createIterator() {
        return new ComputerCollegeIterator(departments);
    }
}



public class InfoCollege implements College {
    private List<Department> departments;

    public InfoCollege() {
        this.departments = new ArrayList<>();
        addDepartment("信息安全", "信息安全");
        addDepartment("网络安全", "网络安全");
        addDepartment("通信安全", "通信安全");
    }

    @Override
    public String getName() {
        return "info-college";
    }

    @Override
    public void addDepartment(String name, String description) {
        departments.add(new Department(name, description));
    }

    @Override
    public Iterator createIterator() {
        return new InfoCollegeIterator(departments);
    }
}
迭代器
public class ComputerCollegeIterator implements Iterator {
    private Department[] departments;
    private int position = 0;

    public ComputerCollegeIterator(Department[] departments) {
        this.departments = departments;
    }

    @Override
    public boolean hasNext() {
        return position < departments.length && departments[position] != null;
    }

    @Override
    public Object next() {
        Department department = departments[position];
        position += 1;

        return department;
    }
}


public class InfoCollegeIterator implements Iterator {
    private List<Department> departments;
    private int index = -1;

    public InfoCollegeIterator(List<Department> departments) {
        this.departments = departments;
    }

    @Override
    public boolean hasNext() {
        if (index >= departments.size() - 1) {
            return false;
        } else {
            index += 1;
            return true;
        }
    }

    @Override
    public Object next() {
        return departments.get(index);
    }
}
输出实现
public class OutputImpl {
    private List<College> colleges;

    public OutputImpl(List<College> colleges) {
        this.colleges = colleges;
    }

    public void printCollege() {
        Iterator<College> iterator = colleges.iterator();
        while (iterator.hasNext()) {
            College college = iterator.next();
            System.out.println("************************");
            System.out.println(college.getName());
            System.out.println("========================");
            printDepartment(college.createIterator());
            System.out.println("========================");
            System.out.println();
        }
    }

    public void printDepartment(Iterator iterator) {
        while (iterator.hasNext()) {
            Department next = (Department) iterator.next();
            System.out.println(next.getName());
        }
    }
}
客户端
public class Client {
    public static void main(String[] args) {
        ArrayList<College> colleges = new ArrayList<>();
        colleges.add(new ComputerCollege());
        colleges.add(new InfoCollege());

        OutputImpl output = new OutputImpl(colleges);

        /*
        ************************
        computer
        ========================
        Java
        PHP
        C
        C++
        C#
        ========================

        ************************
        info-college
        ========================
        信息安全
        网络安全
        通信安全
        ========================
         */
        output.printCollege();
    }
}

观察者模式

  • 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)

  • 当一个对象被修改时,则会自动通知依赖它的对象。

    观察者
    public interface Observer {
        void update(float temperature, float pressure, float humidity);
    }
    
    
    public class CurrentCondition implements Observer{
        private float temperature;
        private float pressure;
        private float humidity;
    
        @Override
        public void update(float temperature, float pressure, float humidity) {
            this.temperature = temperature;
            this.pressure = pressure;
            this.humidity = humidity;
            System.out.println(toString());
        }
    
        @Override
        public String toString() {
            return "CurrentCondition{" +
                    "temperature=" + temperature +
                    ", pressure=" + pressure +
                    ", humidity=" + humidity +
                    '}';
        }
    }
    
    
    public class BaiDuSite implements Observer {
        private float temperature;
        private float pressure;
        private float humidity;
    
        @Override
        public void update(float temperature, float pressure, float humidity) {
            this.temperature = temperature;
            this.pressure = pressure;
            this.humidity = humidity;
            System.out.println(toString());
        }
    
        @Override
        public String toString() {
            return "BaiDuSite{" +
                    "temperature=" + temperature +
                    ", pressure=" + pressure +
                    ", humidity=" + humidity +
                    '}';
        }
    }
    
    天气数据
    public interface Subject {
        void registerObserver(Observer observer);
    
        void removeObserver(Observer observer);
    
        void notifyObserver();
    }
    
    
    public class WeatherData implements Subject {
        private float temperature;
        private float pressure;
        private float humidity;
        private ArrayList<Observer> observers;
    
        public WeatherData() {
            observers = new ArrayList<>();
        }
    
        public void setData(float temperature, float pressure, float humidity) {
            this.temperature = temperature;
            this.pressure = pressure;
            this.humidity = humidity;
            this.notifyObserver();
        }
    
        @Override
        public void registerObserver(Observer observer) {
            observers.add(observer);
        }
    
        @Override
        public void removeObserver(Observer observer) {
            observers.remove(observer);
        }
    
        @Override
        public void notifyObserver() {
            for (Observer observer : observers) {
                observer.update(temperature, pressure, humidity);
            }
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            WeatherData data = new WeatherData();
            CurrentCondition condition = new CurrentCondition();
            data.registerObserver(condition);
    
            //CurrentCondition{temperature=10.0, pressure=100.0, humidity=30.0}
            data.setData(10f,100f,30f);
    
            BaiDuSite baiDuSite = new BaiDuSite();
            data.registerObserver(baiDuSite);
    
            /*
             * CurrentCondition{temperature=11.0, pressure=99.0, humidity=20.9}
             * BaiDuSite{temperature=11.0, pressure=99.0, humidity=20.9}
             */
            data.setData(11f,99f,20.9f);
        }
    }
    

中介者模式

  • 中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。

  • 这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。

    用户
    public class User {
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public User(String name) {
            this.name = name;
        }
    
        public void sendMessage(String message) {
            System.out.println(new Date().toString()
                    + " [" + name + "] : " + message);
        }
    }
    
    中介
    public class Mediator {
        public static void main(String[] args) {
            User pony = new User("Pony");
            User jack = new User("Jack");
    
            /*
             * Sat Feb 13 15:39:42 CST 2021 [Pony] : Hi! Jack!
             * Sat Feb 13 15:39:42 CST 2021 [Jack] : Hello! Pony!
             */
            pony.sendMessage("Hi! Jack!");
            jack.sendMessage("Hello! Pony!");
        }
    }
    

备忘录模式

  • 备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。
来源
public class Originator {
    private String state;

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public Memento saveState() {
        return new Memento(state);
    }
}
备忘录
public class Memento {
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}
管理者
public class Caretaker {
    private List<Memento> mementos = new ArrayList<>();

    public void add(Memento memento) {
        mementos.add(memento);
    }

    public Memento get(int index) {
        return mementos.get(index);
    }
}
客户端
public class Client {
    public static void main(String[] args) {
        Originator originator = new Originator();
        Caretaker caretaker = new Caretaker();

        originator.setState("状态#1 余额999");
        caretaker.add(originator.saveState());

        originator.setState("状态#2 余额666");
        caretaker.add(originator.saveState());

        originator.setState("状态#3 余额333");
        caretaker.add(originator.saveState());

        /**
         * 当前状态:
         * 状态#3 余额333
         */
        System.out.println(originator.getState());
        /**
         * 恢复到状态1:
         * 状态#1 余额999
         */
        originator.setState(caretaker.get(0).getState());
        System.out.println(originator.getState());
    }
}

解释器模式

  • 解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式。

  • 这种模式实现了一个表达式接口,该接口解释一个特定的上下文。

    表达式
    public abstract class Expression {
        public abstract int interpreter(HashMap<String, Integer> var);
    }
    
    
    public class VarExpression extends Expression {
        private String key;
    
        public VarExpression(String key) {
            this.key = key;
        }
    
        @Override
        public int interpreter(HashMap<String, Integer> var) {
            return var.get(key);
        }
    }
    
    
    public abstract class SymbolExpression extends Expression {
        private Expression left;
        private Expression right;
    
        public SymbolExpression(Expression left, Expression right) {
            this.left = left;
            this.right = right;
        }
    
        public Expression getLeft() {
            return left;
        }
    
        public Expression getRight() {
            return right;
        }
    }
    
    
    public class AddExpression extends SymbolExpression {
        public AddExpression(Expression left, Expression right) {
            super(left, right);
        }
    
        @Override
        public int interpreter(HashMap<String, Integer> var) {
            return super.getLeft().interpreter(var) + super.getRight().interpreter(var);
        }
    }
    
    
    public class SubExpression extends SymbolExpression {
        public SubExpression(Expression left, Expression right) {
            super(left, right);
        }
    
        @Override
        public int interpreter(HashMap<String, Integer> var) {
            return super.getLeft().interpreter(var) - super.getRight().interpreter(var);
        }
    }
    
    计算器
    public class Calculator {
        private Expression expression;
    
        public Calculator(String expression) {
            Stack<Expression> stack = new Stack<>();
            char[] chars = expression.toCharArray();
    
            Expression left;
            Expression right;
    
            for (int i = 0; i < chars.length; i++) {
                switch (chars[i]) {
                    case '+':
                        left = stack.pop();
                        right = new VarExpression(String.valueOf(chars[++i]));
                        stack.push(new AddExpression(left, right));
                        break;
                    case '-':
                        left = stack.pop();
                        right = new VarExpression(String.valueOf(chars[++i]));
                        stack.push(new SubExpression(left, right));
                        break;
                    default:
                        stack.push(new VarExpression(String.valueOf(chars[i])));
                        break;
                }
            }
    
            this.expression = stack.pop();
        }
    
        public int run(HashMap<String, Integer> var) {
            return this.expression.interpreter(var);
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            HashMap<String, Integer> var = new HashMap<>();
            var.put("a", 6);
            var.put("b", 5);
            Calculator calculator = new Calculator("a+b");
    
            //11
            System.out.println(calculator.run(var));
        }
    }
    

状态模式

  • 在状态模式(State Pattern)中,类的行为是基于它的状态改变的。

  • 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的对象。

    活动
    public class RaffleActivity {
        private State state;
        private int count;
    
        private State noRaffle = new NoRaffle(this);
        private State canRaffle = new CanRaffle(this);
        private State dispense = new Dispense(this);
        private State dispenseOut = new DispenseOut(this);
    
        public RaffleActivity(int count) {
            this.state = getNoRaffle();
            this.count = count;
        }
    
        public void deductMoney() {
            state.deductMoney();
        }
    
        public void raffle() {
            state.raffle();
        }
    
        public void dispensePrize() {
            state.dispensePrize();
        }
    
        public void setState(State state) {
            this.state = state;
        }
    
        public State getState() {
            return state;
        }
    
        public int getCount() {
            return --count;
        }
    
        public State getNoRaffle() {
            return noRaffle;
        }
    
        public State getCanRaffle() {
            return canRaffle;
        }
    
        public State getDispense() {
            return dispense;
        }
    
        public State getDispenseOut() {
            return dispenseOut;
        }
    }
    
    状态
    public interface State {
        /**
         * 扣积分
         */
        void deductMoney();
    
        /**
         * 是否中奖
         */
        boolean raffle();
    
        /**
         * 颁奖
         */
        void dispensePrize();
    }
    
    
    public class NoRaffle implements State {
        private RaffleActivity activity;
    
        public NoRaffle(RaffleActivity activity) {
            this.activity = activity;
        }
    
        @Override
        public void deductMoney() {
            System.out.println("扣除50积分,可以抽奖了");
            activity.setState(activity.getCanRaffle());
        }
    
        @Override
        public boolean raffle() {
            System.out.println("请先扣除积分");
            return false;
        }
    
        @Override
        public void dispensePrize() {
            System.out.println("不能发放奖品");
        }
    }
    
    
    public class CanRaffle implements State {
        private RaffleActivity activity;
    
        public CanRaffle(RaffleActivity activity) {
            this.activity = activity;
        }
    
        @Override
        public void deductMoney() {
            System.out.println("你已扣取积分");
        }
    
        @Override
        public boolean raffle() {
            System.out.println("正在抽奖");
            Random random = new Random();
            int i = random.nextInt(5);
            if (i == 0) {
                activity.setState(activity.getDispense());
                return true;
            } else {
                System.out.println("很遗憾,您没有中奖!");
                activity.setState(activity.getNoRaffle());
                return false;
            }
        }
    
        @Override
        public void dispensePrize() {
            System.out.println("很遗憾,您没有中奖!");
        }
    }
    
    
    public class Dispense implements State {
        private RaffleActivity activity;
    
        public Dispense(RaffleActivity activity) {
            this.activity = activity;
        }
    
        @Override
        public void deductMoney() {
            System.out.println("不能抽奖");
        }
    
        @Override
        public boolean raffle() {
            System.out.println("不能抽奖");
            return false;
        }
    
        @Override
        public void dispensePrize() {
            if (activity.getCount() > 0) {
                System.out.println("你正在领奖");
                activity.setState(activity.getNoRaffle());
            } else {
                System.out.println("奖品已领完");
                activity.setState(activity.getDispenseOut());
            }
        }
    }
    
    
    public class DispenseOut implements State {
        private RaffleActivity activity;
    
        public DispenseOut(RaffleActivity activity) {
            this.activity = activity;
        }
    
        @Override
        public void deductMoney() {
            System.out.println("奖品已领完");
        }
    
        @Override
        public boolean raffle() {
            System.out.println("奖品已领完");
            return false;
        }
    
        @Override
        public void dispensePrize() {
            System.out.println("奖品已领完");
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            int count = 3;
            RaffleActivity activity = new RaffleActivity(count);
    
            /**
             *============1===========
             * 扣除50积分,可以抽奖了
             * 正在抽奖
             * 你正在领奖
             *
             * ============2===========
             * 扣除50积分,可以抽奖了
             * 正在抽奖
             * 很遗憾,您没有中奖!
             * 不能发放奖品
             *
             * ============3===========
             * 扣除50积分,可以抽奖了
             * 正在抽奖
             * 很遗憾,您没有中奖!
             * 不能发放奖品
             *
             * ============4===========
             * 扣除50积分,可以抽奖了
             * 正在抽奖
             * 奖品已领完
             *
             * ============5===========
             * 奖品已领完
             * 奖品已领完
             * 奖品已领完
             */
            for (int i = 1; i <= count + 2; i++) {
                System.out.println("============" + i + "===========");
                activity.getCount();
                activity.deductMoney();
                activity.raffle();
                activity.dispensePrize();
                System.out.println();
            }
        }
    }
    

策略模式

  • 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。

  • 在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的对象。策略对象改变对象的执行算法。

    行为
    public interface FlyBehavior {
        void fly();
    }
    
    
    public class GoodFlyBehavior implements FlyBehavior {
        @Override
        public void fly() {
            System.out.println("GoodFlyBehavior");
        }
    }
    
    
    public class NoFlyBehavior implements FlyBehavior {
        @Override
        public void fly() {
            System.out.println("NoFlyBehavior");
        }
    }
    
    public class BadFlyBehavior implements FlyBehavior {
        @Override
        public void fly() {
            System.out.println("BadFlyBehavior");
        }
    }
    
    public abstract class Duck {
        public FlyBehavior behavior;
    
        public abstract void display();
    
        public void quack() {
            System.out.println("嘎嘎叫");
        }
    
        public void swim() {
            System.out.println("游泳");
        }
    
        public void fly() {
            behavior.fly();
        }
    }
    
    
    public class PekingDuck extends Duck {
        public PekingDuck() {
            behavior = new NoFlyBehavior();
        }
    
        @Override
        public void display() {
            System.out.println("PekingDuck");
        }
    
        @Override
        public void fly() {
            super.fly();
        }
    }
    
    
    public class WildDuck extends Duck {
        public WildDuck() {
            behavior = new GoodFlyBehavior();
        }
    
        @Override
        public void display() {
            System.out.println("WildDuck");
        }
    
        @Override
        public void fly() {
            super.fly();
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            PekingDuck pekingDuck = new PekingDuck();
    
            /*
             * PekingDuck
             * NoFlyBehavior
             */
            pekingDuck.display();
            pekingDuck.fly();
    
            WildDuck wildDuck = new WildDuck();
    
            /*
             * WildDuck
             * GoodFlyBehavior
             */
            wildDuck.display();
            wildDuck.fly();
        }
    }
    

职责链模式

  • 职责链模式(Chain of Responsibility Pattern):避免将一个请求的发送者与接受者耦合在一起,让多个对象都有机会处理请求。将接受请求的对象接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。

    职责链
    public abstract class Approve {
        Approve approve;
        String name;
    
        public Approve(String name) {
            this.name = name;
        }
    
        public void setApprove(Approve approve) {
            this.approve = approve;
        }
    
        public abstract void processRequest(PurchaseRequest request);
    }
    
    
    public class DepartmentApprove extends Approve {
        public DepartmentApprove(String name) {
            super(name);
        }
    
        @Override
        public void processRequest(PurchaseRequest request) {
            if (request.getPrice() <= 5000) {
                System.out.println("请求被DepartmentApprove处理");
            } else {
                approve.processRequest(request);
            }
        }
    }
    
    
    public class CollegeApprove extends Approve {
        public CollegeApprove(String name) {
            super(name);
        }
    
        @Override
        public void processRequest(PurchaseRequest request) {
            System.out.println("请求被CollegeApprove处理");
        }
    }
    
    购买请求
    public class PurchaseRequest {
        private int type;
        private float price;
        private int id;
    
        public PurchaseRequest(int type, float price, int id) {
            this.type = type;
            this.price = price;
            this.id = id;
        }
    
        public int getType() {
            return type;
        }
    
        public float getPrice() {
            return price;
        }
    
        public int getId() {
            return id;
        }
    }
    
    客户端
    public class Client {
        public static void main(String[] args) {
            PurchaseRequest request1 = new PurchaseRequest(1, 3000, 1);
            PurchaseRequest request2 = new PurchaseRequest(1, 50001, 1);
    
            DepartmentApprove departmentApprove = new DepartmentApprove("DepartmentApprove");
            CollegeApprove collegeApprove = new CollegeApprove("CollegeApprove");
            departmentApprove.setApprove(collegeApprove);
    
            /*
             * 请求被DepartmentApprove处理
             * 请求被CollegeApprove处理
             * 请求被CollegeApprove处理
             * 请求被CollegeApprove处理
             */
            departmentApprove.processRequest(request1);
            departmentApprove.processRequest(request2);
            collegeApprove.processRequest(request1);
            collegeApprove.processRequest(request2);
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值