设计模式

设计模式目的

为了让程序有更好的一下特性:

  • 可读性
  • 代码重用性
  • 可扩展性(可维护性):方便增加功能
  • 可靠性:增加功能不影响原先的功能
  • 高内聚、低耦合

设计模式核心思想

把应用中可能发生变化的代码独立出来,不与不需要变化的代码混合。

设计模式原则

设计模式依据的原则

单一职责原则

一个类只负责一项职责

提高类的可读性、可扩展性

案例
public class Case1 {
    //使用方
    public static void main(String[] args) {
        infantry solider = new infantry();
        solider.action("步兵");
        solider.action("指挥官");
        solider.action("飞行员");
    }
}
class Solider {
    public void action(String solider) {
        System.out.println(solider + "在陆地前线战斗!");
    }
}

步兵在陆地前线战斗!
指挥官在陆地前线战斗!
飞行员在陆地前线战斗!

改进1
  • 方法上遵循单一职责原则
  • 修改较少
public class Case2 {
    public static void main(String[] args) {
        Solider solider = new Solider();
        solider.action1("步兵");
        solider.action2("指挥官");
    }
}
class Solider {

    //方法上遵循单一职责原则
    public void action1(String solider) {
        System.out.println(solider + "在陆地前线战斗!");
    }

    public void action2(String solider) {
        System.out.println(solider + "指挥战斗!");
    }
}
改进2
  • 类中遵循单一职责原则
  • 将类拆分,修改较大,需要修改客户端
public class Case3 {
    //使用方
    public static void main(String[] args) {

        //需要修改使用方
        infantry solider = new infantry();
        Commander commander = new Commander();
        solider.action("步兵");
        commander.action("指挥官");
    }
}
//将Solider类拆分,遵循单一职责原则
class infantry {
    public void action(String solider) {
        System.out.println(solider + "在陆地前线战斗!");
    }
}

class Commander {
    public void action(String solider) {
        System.out.println(solider + "指挥战斗!");
    }
}

类中的方法较少时考虑使用

接口隔离原则

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

案例
interface Interface1 {
    void method1ForA();

    void method2ForA();

    void methodForAB();

    void method1ForB();

    void method2ForB();
}
class ClassA implements Interface1 {

    @Override
    public void method1ForA() {
    }

    @Override
    public void method2ForA() {

    }

    @Override
    public void methodForAB() {

    }

    @Override
    public void method1ForB() {

    }

    @Override
    public void method2ForB() {

    }
}
class ClassB implements Interface1 {

    @Override
    public void method1ForA() {

    }

    @Override
    public void method2ForA() {

    }

    @Override
    public void methodForAB() {

    }

    @Override
    public void method1ForB() {

    }

    @Override
    public void method2ForB() {

    }
}
class ClassNeedA {
    public void depend1(Interface1 interface1) {
        interface1.method1ForA();
    }

    public void depend2(Interface1 interface1) {
        interface1.method2ForA();
    }

    public void depend3(Interface1 interface1) {
        interface1.methodForAB();
    }
}
class ClassNeedB {
    public void depend1(Interface1 interface1) {
        interface1.method1ForB();
    }

    public void depend2(Interface1 interface1) {
        interface1.method2ForB();
    }

    public void depend3(Interface1 interface1) {
        interface1.methodForAB();
    }
}
改进

在这里插入图片描述

interface Interface2 {
    void method1ForA();

    void method2ForA();
}

interface Interface3 {
    void method1ForB();

    void method2ForB();
}

interface Interface4 {
    void methodForAB();
}
class ClassA1 implements Interface2, Interface4 {

    @Override
    public void method1ForA() {

    }

    @Override
    public void method2ForA() {

    }

    @Override
    public void methodForAB() {

    }
}
class ClassB1 implements Interface3, Interface4 {

    @Override
    public void method1ForB() {

    }

    @Override
    public void method2ForB() {

    }

    @Override
    public void methodForAB() {

    }
}
class ClassNeedA1 {
    public void depend1(Interface2 interface2) {
        interface2.method1ForA();
    }

    public void depend2(Interface2 interface2) {
        interface2.method2ForA();
    }

    public void depend3(Interface4 interface4) {
        interface4.methodForAB();
    }
}
class ClassNeedB1 {
    public void depend1(Interface3 interface3) {
        interface3.method1ForB();
    }

    public void depend3(Interface3 interface3) {
        interface3.method2ForB();
    }

    public void depend3(Interface4 interface4) {
        interface4.methodForAB();
    }
}

依赖倒置原则

  • 高层模块不应该依赖低层模块,二者都应该依赖其抽象
  • 抽象不应该依赖细节,细节应该依赖抽象
  • 中心思想:面向接口编程
  • 使用抽象类、接口制定规范,而把展示细节任务交给他们的实现类
案例
public class Case1 {
    public static void main(String[] args) {
        SmartController smartController = new SmartController();
        TV tv = new TV();
        
        smartController.control(tv);
        smartController.control(new AirConditioner());
    }
}
class TV {
    public String turnOn() {
        return "电视开机";
    }
}

class AirConditioner {
    public String turnOn() {
        return "空调开机";
    }
}
class SmartController {
    public void control(TV tv) {
        System.out.println(tv.turnOn());
    }

    //添加一个新的方法,重载方法
    public void control(AirConditioner airConditioner) {
        System.out.println(airConditioner.turnOn());
    }
}

增加其他家居,需要添加方法,控制器与具体的家居耦合度过高

改进

在这里插入图片描述

public class Case2 {
    public static void main(String[] args) {
        TV1 tv = new TV1();
        SmartController1 smartController1 = new SmartController1();
        smartController1.control(tv);//接口传递

        SmartController1 smartController2 = new SmartController1(new AirConditioner1());//构造器传递
        smartController2.control();
        smartController2.setter(tv);//setter方法传递
        smartController2.control();
    }
}
interface SmartHome {
    String turnOn();
}
class TV1 implements SmartHome {
    public String turnOn() {
        return "电视开机";
    }
}

class AirConditioner1 implements SmartHome {
    public String turnOn() {
        return "空调开机";
    }
}
class SmartController1 {
    //构造器传递、setter传递所需成员变量,引用实现类对象
    private SmartHome smartHome;

    public SmartController1() {

    }

    //构造器传递所需构造器,传递实现类对象
    public SmartController1(SmartHome smartHome) {
        this.smartHome = smartHome;
    }

    //setter方法传递所需方法,传递实现类对象
    public void setter(SmartHome smartHome) {
        this.smartHome = smartHome;
    }
    
    //接口传递所需方法,控制实现类
    public void control(SmartHome smartHome) {
        System.out.println(smartHome.turnOn());
    }

    //构造器传递、setter传递所需方法,控制实现类
    public void control() {
        System.out.println(smartHome.turnOn());
    }
}

抽象不应该依赖细节,细节应该依赖抽象

里氏替换原则

  • 所有引用基类的地方必须能透明地使用其子类的对象
  • 子类可以扩展父类的功能,但不能改变父类的功能(尽量不重写、不重载父类的方法)
  • 子类可以增加特有的功能
  • 子类的方法重载父类的方法时,方法的前置条件(方法的形参)要比父类方法的输入参数更宽松。
  • 子类的方法实现父类的抽象方法时,方法的后置条件(方法的返回值)要比父类更严格
案例
public class Case1 {
    public static void main(String[] args) {
        Worker worker = new Worker();
        Student student = new Student();

        System.out.println("社会上使用" + worker.printInfo());

        System.out.println("学校里使用" + student.printInfo());
        System.out.println("社会上使用" + student.printInfo());//应该调用父类的方法获取个人信息,但方法被重写
    }
}
class Worker {
    public String printInfo() {
        return "个人信息";
    }
}

class Student extends Worker {
    public String printInfo() {
        return "学生信息";
    }
}

违背了里氏替换原则

改进
  1. 不重写父类方法,而新增一个子类方法
  2. 父类、子类继承一个基类
  3. 使用组合关系,父类对象作为子类的属性

迪米特原则(最少知道原则)

  • 一个对象应该对其他对象保持最少的了解,对自己依赖的类知道得越少越好
  • 直接朋友:对象之间会有耦合关系,出现在成员变量、方法参数、方法返回值的类
  • 陌生类不要以局部变量形式存在
案例
public class Case1 {
    public static void main(String[] args) {
        ArrayList<Member> members = new ArrayList<>();
        Boss boss = new Boss();
        for (int i = 0; i < 5; i++) {
            members.add(new Member(i));
        }

        Leader leader = new Leader(members);
        boss.getTeamInfo(leader);
    }
}
class Member {
    public int id;

    public Member(int id) {
        this.id = id;
    }
}
class Leader {
    private List<Member> members;

    public Leader(ArrayList<Member> members) {
        this.members = members;
    }

    public List<Member> getMembers() {
        return members;
    }
}
class Boss {
    public void getTeamInfo(Leader leader) {
        List<Member> members = leader.getMembers();//局部变量不是直接朋友
        System.out.println("团队成员有:");
        for (Member member : members) {
            System.out.println("员工ID:" + member.id);
        }
    }
}
改进

在这里插入图片描述
在这里插入图片描述

public class Case2 {
    public static void main(String[] args) {
        ArrayList<Member> members = new ArrayList<>();
        Boss boss = new Boss();
        for (int i = 0; i < 5; i++) {
            members.add(new Member(i));
        }

        Leader leader = new Leader(members);
        boss.getTeamInfo(leader);
    }
}
class Leader1 {
    private List<Member> members;

    public Leader1(ArrayList<Member> members) {
        this.members = members;
    }

    public List<Member> getMembers() {
        return members;
    }
	
	//打印信息的方法交给组长
    public void printTeamInfo() {
        System.out.println("团队成员有:");
        for (Member member : members) {
            System.out.println("员工ID:" + member.id);
        }
    }
}
class Boss1 {
    public void getTeamInfo(Leader1 leader) {
        leader.printTeamInfo();
    }
}

合成复用原则

  • 尽量使用合成、内聚的方式,而不使用继承
  • 交互对象之间尽量做到松耦合
例子
public class Case1 {
    public static void main(String[] args) {
        B b = new B(new A());
        b.method();
    }
}
class A {
    public void method1() {
        System.out.println("A中方法1");
    }

    public void method2() {
        System.out.println("A中方法2");
    }

    public void method3() {
        System.out.println("A中方法3");
    }
}
class B {
    private A a;//A为B的成员变量

    public B(A a) {
        this.a = a;
    }

    public void method() {
        a.method1();
        a.method2();
        a.method3();
    }
}

开闭原则

  • 一个软件实体如类、模块和函数应该对扩展开放(提供方),对修改关闭(使用方)
  • 通过扩展软件实体完成变化、而不是修改现有代码
  • 最基础的设计原则,遵守其他原则也就遵守开闭原则
案例
public class Case1 {
    public void create(Shape shape) {
        String name = shape.name;
        if (name == "圆") {
            createCircle();
        } else if (shape.name == "长方形") {//添加其他图形需要修改代码
            createRectangle();
        } else {
            System.out.println("未知图形");
        }
    }

    //添加其他图形需要在使用方添加方法
    public void createCircle() {
        System.out.println("需要半径,以生成圆");
    }

    public void createRectangle() {
        System.out.println("需要长、宽,以生成长方形");
    }

    public static void main(String[] args) {
        Case1 case1 = new Case1();
        case1.create(new Circle());
    }
}
class Shape {
    String name;
}
class Circle extends Shape {
    Circle() {
        name = "圆";
    }
}
class Rectangle extends Shape {
    Rectangle() {
        name = "长方形";
    }
}
改进
public class Case2 {
    public void create(Shape1 shape) {
        shape.create();
    }

    public static void main(String[] args) {
        Case1 case1 = new Case1();

        //对修改关闭,使用方无需修改
        case1.create(new Circle());
        case1.create(new Rectangle());
    }
}
//对提供方扩展开放,增加其他图形时继承抽象类,重写方法
abstract class Shape1 {
    String name;

    abstract void create();
}
class Circle1 extends Shape1 {
    Circle1() {
        name = "圆";
    }

    @Override
    void create() {
        System.out.println("需要半径,以生成圆");
    }
}
class Rectangle1 extends Shape1 {
    Rectangle1() {
        name = "长方形";
    }

    @Override
    void create() {
        System.out.println("需要长、宽,以生成长方形");
    }
}

设计模式

单例模式

饿汉式
  • 线程安全,确定一定会使用实例使用
  • 其他方式
    • 静态代码块方式初始化方式
public class SingletonTest1 {
    public static void main(String[] args) {
        System1 system1 = System1.getInstance();
    }
}
//饿汉式
class System1 {
    private static final System1 SYSTEM = new System1();

    //将构造器私有化
    private System1() {

    }

    public static System1 getInstance() {
        return SYSTEM;
    }
}
懒汉式
  • 其他方式
    • 不使用同步,线程不安全
    • 同步方法,效率低
    • 同步代码块,效率低
    • 静态内部类:加载外部类不会加载内部类,第一次使用内部类时才加载类,并且加载类时是线程安全的
    • 枚举
双重检查
public class SingletonTest2 {
    public static void main(String[] args) {
        System2 system = System2.getInstance();
    }
}
//懒汉式,双重检查
class System2 {
    private static volatile System2 system;

    private System2() {

    }

    public static System2 getInstance() {
        if (system == null) {
            synchronized (System2.class) {
                if (system == null) {
                    system = new System2();
                }
            }
        }
        return system;
    }
}
内部类
public class SingletonTest3 {
    public static void main(String[] args) {
    }
}
class System3 {
    private System3() {

    }

    private static final class SystemInner {
        private static final System3 SYSTEM = new System3();
    }

    public System3 getInstance() {
        return SystemInner.SYSTEM;
    }
}
枚举
public class SingletonTest4 {
    public static void main(String[] args) {
        System4 system = System4.SYSTEM;
    }
}

enum System4 {
    SYSTEM
}

工厂模式

简单工厂模式

在这里插入图片描述

抽象工厂模式

在这里插入图片描述

简单工厂模式
public class PhoneFactory1 {// 简单工厂把创建者、调用者分离
	public static Phone getPhone(char c) {// 对新增产品,不修改代码则无法扩展,违反开闭原则
		if (c == 'A')
			return new Aphone();
		else if (c == 'B')
			return new Bphone();
		else
			return null;
	}

	public static void main(String[] args) {
		Phone phone1 = PhoneFactory1.getPhone('A');
		Phone phone2 = PhoneFactory1.getPhone('B');
		phone1.call();
		phone2.capture();

		System.out.println();

		Phone phone3 = new APhoneFactory().getPhone();
		Phone phone4 = new BPhoneFactory().getPhone();
		phone3.call();
		phone4.capture();
	}
}
抽象工厂模式
public class FactoryTest2 {
    public static void main(String[] args) {
        APhoneFactory aPhoneFactory = new APhoneFactory();
        BPhoneFactory bPhoneFactory = new BPhoneFactory();

        EarPhone earPhoneA = aPhoneFactory.getEarPhone();
        Phone phoneA = aPhoneFactory.getPhone();

        EarPhone earPhoneB = bPhoneFactory.getEarPhone();
        Phone phoneB = bPhoneFactory.getPhone();

        earPhoneA.play();
        earPhoneB.play();

        phoneA.call();
        phoneB.call();
    }
}
interface PhoneFactory2 {//工厂方法模式有一组实现了相同接口的工厂类

    Phone getPhone();

    EarPhone getEarPhone();
}
class APhoneFactory implements PhoneFactory2 {

    public Aphone getPhone() {
        return new Aphone();
    }

    @Override
    public EarPhone getEarPhone() {
        return new AEarPhone();
    }

}
class BPhoneFactory implements PhoneFactory2 {

    public Bphone getPhone() {
        return new Bphone();
    }

    @Override
    public EarPhone getEarPhone() {
        return new BEarPhone();
    }
}

原型模式

  • 指定创建对象的种类,通过拷贝原型创建新的对象
相关类的信息
class Phone1 implements Cloneable, Serializable {//序列化为使用序列化方式时所需要
    private static final long serialVersionUID = 1L;

    private String name;
    private CPU cpu;

    public String getName() {
        return name;
    }

    public CPU getCpu() {
        return cpu;
    }

    public Phone1(String name, CPU cpu) {
        this.name = name;
        this.cpu = cpu;
    }
}
class CPU implements Cloneable, Serializable {//序列化为使用序列化方式时所需要
    public String name;

    public CPU(String name) {
        this.name = name;
    }

    public CPU Clone() {//深拷贝时需要
        CPU cpu = null;
        try {
            cpu = (CPU) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return cpu;
    }
}
使用方使用
public class prototypeTest2 {
    public static void main(String[] args) {
        Phone1 phone = new Phone1("A", new CPU("011"));
        Phone1 phone1 = phone.clone();
        Phone1 phone2 = phone.clone1();
        System.out.printf("%s的哈希值:%s,CPU的哈希值:%s%n", phone.getName(), phone.hashCode(), phone.getCpu().hashCode());
        System.out.printf("%s的哈希值:%s,CPU的哈希值:%s%n", phone1.getName(), phone1.hashCode(), phone1.getCpu().hashCode());
        System.out.printf("%s的哈希值:%s,CPU的哈希值:%s%n", phone2.getName(), phone2.hashCode(), phone2.getCpu().hashCode());
    }
}
重写clone方法(浅拷贝)
public Phone clone() {
        Phone phone = null;
        try {
            phone = (Phone) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return phone;
    }
深拷贝
public Phone1 clone() {
        Phone1 phone = null;
        try {
            phone = (Phone1) super.clone();
            phone.cpu = (CPU) cpu.Clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return phone;
    }
序列化深拷贝
public Phone1 clone1() {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        Phone1 phone = null;

        try (bos; ObjectOutputStream oos = new ObjectOutputStream(bos)) {
            oos.writeObject(this);
            bis = new ByteArrayInputStream(bos.toByteArray());

            ois = new ObjectInputStream(bis);
            phone = (Phone1) ois.readObject();
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return phone;
    }

建造者模式

  • 使用者不需要知道产品内部细节
  • 产品本身与产品创建过程解耦
  • 建造者之间相对独立,使用不同的建造者便可创建不同的产品
  • 将复杂产品的创建分解在不同的方法中
  • 增加具体的建造者、指挥者聚合抽象建造者,符合开闭原则
  • 产品内部比较复杂,产品有共同点适合使用,产品间差异大不适合使用建造者
  • 建造者模式按照指定蓝图创建产品(对创建的过程有要求),而工厂模式注重不同家族产品整体创建方法

在这里插入图片描述

public class BuilderTest1 {
    public static void main(String[] args) {
        Aphonebuilder aphonebuilder = new Aphonebuilder();
        Bphonebuilder bphonebuilder = new Bphonebuilder();

        Director director = new Director(aphonebuilder);
        Phone phoneA = director.build();
        System.out.println(phoneA.getPart1() + ' ' + phoneA.getPart2());

        director.setBuilder(bphonebuilder);
        Phone phoneB = director.build();
        System.out.println(phoneB.getPart1() + ' ' + phoneB.getPart2());
    }
}
class Phone {
    private String part1;

    private String part2;

    public void setPart1(String part1) {
        this.part1 = part1;
    }

    public void setPart2(String part2) {
        this.part2 = part2;
    }

    public String getPart1() {
        return part1;
    }

    public String getPart2() {
        return part2;
    }
}
abstract class PhoneBuilder {
    protected Phone phone = new Phone();

    abstract void buildPart1();

    abstract void buildPart2();

    public Phone getPhone() {
        return phone;
    }
}
class Aphonebuilder extends PhoneBuilder {

    @Override
    void buildPart1() {
        System.out.println("A建造部分1");
        phone.setPart1("A part 1");
    }

    @Override
    void buildPart2() {
        System.out.println("A建造部分2");
        phone.setPart2("A part 2");
    }
}
class Bphonebuilder extends PhoneBuilder {

    @Override
    void buildPart1() {
        System.out.println("B建造部分1");
        phone.setPart1("B part 2");
    }

    @Override
    void buildPart2() {
        System.out.println("B建造部分2");
        phone.setPart2("B part 2");

    }
}
class Director {
    private PhoneBuilder phoneBuilder;

    public Director(PhoneBuilder builder) {
        phoneBuilder = builder;
    }

    public void setBuilder(PhoneBuilder phoneBuilder) {
        this.phoneBuilder = phoneBuilder;
    }

    public Phone build() {
        phoneBuilder.buildPart1();
        phoneBuilder.buildPart2();
        return phoneBuilder.getPhone();
    }
}

适配器模式

  • 作为两个不兼容的接口之间的桥梁
  • 对象适配器使用关联关系(聚合)来代替继承关系,合成复用原则
角色
  • 被适配者
  • 适配器
  • 目标:需要适配器的输出
类适配器

在这里插入图片描述

对象适配器

在这里插入图片描述

接口适配器

在这里插入图片描述

public class AdapterTest1 {
    public static void main(String[] args) {
        Outlet outlet = new Outlet();
        Phone phone = new Phone();
        phone.charge(new Adapter1());
        phone.charge(new Adapter2(outlet));

        AbstractAdapter adapter = new AbstractAdapter(outlet) {
            @Override
            public String output9V() {
                System.out.println("适配器输入电压为" + outlet.output220V());
                System.out.println("变压");
                System.out.println("适配器输出电压为9V");
                return "9V";
            }
        };
        phone.charge(adapter);
    }
}
class Outlet {
    public String output220V() {
        return "220V";
    }
}
interface TypeC {
    String output9V();
}
class Phone {
    public void charge(TypeC typeC) {
        System.out.println("手机充电电压为" + typeC.output9V());
    }
}
class Adapter1 extends Outlet implements TypeC {

    @Override
    public String output9V() {
        System.out.println("适配器输入电压为" + output220V());
        System.out.println("适配器输出电压为9V");
        return "9V";
    }
}
对象适配器

将被适配者作为对象

class Adapter2 implements TypeC {
    private Outlet outlet;

    Adapter2(Outlet outlet) {
        this.outlet = outlet;
    }

    @Override
    public String output9V() {
        System.out.println("适配器输入电压为" + outlet.output220V());
        System.out.println("适配器输出电压为9V");
        return "9V";
    }
}
接口适配器
  • 被适配者作为接口
interface Output {
    String output9V();

    String output5V();
}
abstract class AbstractAdapter implements Output, TypeC {
    protected Outlet outlet;

    public AbstractAdapter(Outlet outlet) {
        this.outlet = outlet;
    }

    //以下方法为默认实现
    @Override
    public String output9V() {
        return outlet.output220V();
    }

    @Override
    public String output5V() {
        return outlet.output220V();
    }
}

桥接模式

  • 将实现、抽象放在两个不同的类层面,使两个层面可以独立改变
  • 多个角度的变化情况下, 因为使用继承而导致类爆炸、扩展不灵活的问题
    在这里插入图片描述
public class BridgeTest1 {
    public static void main(String[] args) {
        HighEndPhone highEndPhoneA = new HighEndPhone(new BrandA());
        LowerEndPhone lowerEndPhoneB = new LowerEndPhone(new BrandB());

        highEndPhoneA.run();
        lowerEndPhoneB.run();
    }
}
interface Brand {
    String run();
}
class BrandA implements Brand {

    @Override
    public String run() {
        return "品牌A的手机运行";
    }
}
class BrandB implements Brand {

    @Override
    public String run() {
        return "品牌B的手机运行";
    }
}
abstract class Phone {
    private Brand brand;

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

    protected void run() {
        System.out.println(brand.run());
    }
}
class HighEndPhone extends Phone {

    public HighEndPhone(Brand brand) {
        super(brand);
    }

    @Override
    protected void run() {
        super.run();
        System.out.println("信息:高端机");
    }
}
class LowerEndPhone extends Phone {

    public LowerEndPhone(Brand brand) {
        super(brand);
    }

    @Override
    protected void run() {
        super.run();
        System.out.println("信息:低端机");
    }
}

装饰者模式

  • 动态地给一个对象添加一些额外的职责使用
  • 不想增加很多子类的情况下扩展类使用

在这里插入图片描述

public class DecoratorTest1 {
    public static void main(String[] args) {
        Drink drink = new MilkTeaA();//8元
        drink = new IngredientA(drink);//2元
        drink = new IngredientA(drink);//2元

        System.out.println(drink.getName());
        System.out.println(drink.cost());
    }
}
abstract class Drink {
    private String name;
    private double price;

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    abstract double cost();
}
class MilkTea extends Drink {
    @Override
    double cost() {
        return getPrice();
    }
}
class MilkTeaA extends MilkTea {
    public MilkTeaA() {
        setName("A奶茶");
        setPrice(8);
    }

}
class MilkTeaB extends MilkTea {
    public MilkTeaB() {
        setName("B奶茶");
        setPrice(10);
    }
}
class Decorator extends Drink {
    private Drink drink;

    public Decorator(Drink drink) {
        this.drink = drink;
    }

    @Override
    double cost() {
        return getPrice() + drink.cost();
    }

    @Override
    public String getName() {
        return drink.getName() + " " + super.getName();
    }
}
class IngredientA extends Decorator {
    public IngredientA(Drink drink) {
        super(drink);
        setName("配料A");
        setPrice(2);
    }
}
class IngredientB extends Decorator {
    public IngredientB(Drink drink) {
        super(drink);
        setName("配料B");
        setPrice(4);
    }
}

组合模式(部分整体模式)

  • 依据树形结构组合对象
  • 要求较高的抽象性
  • 节点的差异大时不适合使用
角色
  • 部件(Component):接口、抽象类
  • 合成品(Componsite):有子部件,上层组织
  • 叶子节点(Leaf):没有子部件,最底层的组织
    在这里插入图片描述
public class CompositeTest1 {
    public static void main(String[] args) {
        University university = new University("大学");

        College college1 = new College("计算机学院");
        College college2 = new College("信息学院");

        Major major1 = new Major("计算机科学与技术");
        Major major2 = new Major("软件工程");

        college1.add(major1);
        college1.add(major2);

        university.add(college1);
        university.add(college2);

        university.printInfo();

        college1.remove(major1);
        college1.printInfo();
        college2.printInfo();

    }
}
class University extends Component {
    private List<Component> organization = new ArrayList<>();

    public University(String name) {
        super(name);
    }

    @Override
    protected void add(Component component) {
        organization.add(component);
    }

    @Override
    protected void remove(Component component) {
        organization.remove(component);
    }

    @Override
    void printInfo() {
        System.out.println("=====" + super.getName() + "=====");
        for (Component component : organization) {
            component.printInfo();
        }
    }
}
class College extends Component {
    private List<Component> organization = new ArrayList<>();

    public College(String name) {
        super(name);
    }

    @Override
    protected void add(Component component) {
        organization.add(component);
    }

    @Override
    protected void remove(Component component) {
        organization.remove(component);
    }

    @Override
    void printInfo() {
        System.out.println("----------" + super.getName() + "----------");
        for (Component component : organization) {
            component.printInfo();
        }
    }
}
class Major extends Component {
    public Major(String name) {
        super(name);
    }

    @Override
    void printInfo() {
        System.out.println(super.getName());
    }
}

外观模式(过程模式)

  • 使用者只通过外观类(高层接口)控制子系统,隐藏了子系统的细节
  • 减少依赖、提高灵活性,但修改不方便,不符合开闭原则
  • 对于少量的子系统,不需要使用外观模式
  • 使用者与子系统解耦
  • 当难以维护大型遗留的系统时,可以考虑新开发一个新系统
角色
  • 外观类
  • 子系统
    在这里插入图片描述
class Employee {
    private Provider provider;
    private Processor processor;
    private Transporter transporter;

    public Employee() {
        provider = new Provider();
        processor = new Processor();
        transporter = new Transporter();
    }

    public void work() {
        String item = provider.provide();
        String product = processor.process(item);
        transporter.transport(product);
    }
}

class Provider {
    public String provide() {
        System.out.println("提供原材料");
        return "原材料";
    }
}

class Processor {
    public String process(String item) {
        System.out.println("加工" + item);
        return "产品";
    }
}

class Transporter {
    public void transport(String product) {
        System.out.println("运输" + product);
    }
}

享元模式

  • 系统中有大量对象
  • 对象的状态大部分可以外部化
  • 内部状态不会随环境的改变而改变
  • 外部状态会随环境改变而改变,不可共享
  • 按照内部状态分组,当把外部状态从对象中剔除出来时,那么每一组对象都可以用一个对象来代替
  • 注意划分外部状态和内部状态,否则可能会引起线程安全问题
  • 这些类必须有一个工厂对象加以控制
    在这里插入图片描述
public class FlyWeightTest1 {
    public static void main(String[] args) {
        Server server = new Server();
        WebPage page1 = server.getPage("内容1");
        WebPage page2 = server.getPage("内容2");

        User user1 = new User("用户1");
        User user2 = new User("用户2");
        User user3 = new User("用户3");

        page1.visit(user1);
        page1.visit(user2);
        page1.visit(user3);
        page2.visit(user1);
        page2.visit(user2);

        System.out.println("页面个数:" + server.getSize());
    }
}
class Server {
    private HashMap<String, WebPage> pool = new HashMap<>();

    public WebPage getPage(String key) {
        if (!pool.containsKey(key)) {
            pool.put(key, new ConcretePage(key));
        }
        return pool.get(key);
    }

    public int getSize() {
        return pool.size();
    }
}
abstract class WebPage {

    abstract public void visit(User user);//参数用以设置外部状态
}
class ConcretePage extends WebPage {
    private String content;//内部状态

    public ConcretePage(String content) {
        this.content = content;
    }

    @Override
    public void visit(User user) {
        System.out.println(user.getName() + "访问页面" + content);
    }
}
class User {
    private String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

代理模式

  • 对一个目标对象提供一个替身控制目标的访问,可以在目标对象实现的基础上,增强额外的功能
角色
  • 被代理类
  • 代理类
静态代理
  • 代理类、被代理类实现相同的接口
  • 缺点:代理类需要实现被代理类的接口、可能产生很多代理类,接口增加方法时,要修改被代理类、代理类

在这里插入图片描述

public class ProxyTest1 {
    public static void main(String[] args) {
        Server server = new Server();
        ProxyServer proxyServer = new ProxyServer(server);
        proxyServer.run();
    }
}
interface Network {
    void browse();
}
class Server implements Network {

    public void browse() {
        System.out.println("真实的服务器浏览");
    }

}
class ProxyServer implements Network {
    private Network server;

    public ProxyServer(Network server) {
        this.server = server;
    }

    public void browse() {
        server.browse();
    }

    void run() {
        System.out.println("检查工作");
        browse();
    }
}
动态代理(接口代理)
  • 代理对象不需要实现接口
  • 动态在内存中构造代理对象
  • 根据传入对象,返回一个代理对象
public class ProxyTest2 {
    public static void main(String[] args) {
        Server1 server1 = new Server1();

        ProxyFactory proxyFactory = new ProxyFactory(server1);
        NetWork1 proxyServer = proxyFactory.getInstance();
        System.out.println("获取:" + proxyServer.browse());
    }
}
interface NetWork1 {
    String browse();
}
class Server1 implements NetWork1 {

    @Override
    public String browse() {
        System.out.println("真实的浏览");
        return "浏览内容";
    }
}
class ProxyFactory {
    private NetWork1 target;

    public ProxyFactory(NetWork1 target) {
        this.target = target;
    }

    public NetWork1 getInstance() {
        return (NetWork1) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    System.out.println("代理服务浏览");
                    Object result = method.invoke(target, args);
                    System.out.println("代理服务完成");
                    return result;
                });
    }
}

模板方法

  • 抽象类定义了算法的结构,子类可以不改变算法的结构而重新定义算法中的特定步骤
  • 修改算法时只修改父类的模板方法
  • 模板方法一般设置为final,使子类不可以重新模板方法
  • 每一个不同的实现需要子类的实现,类的个数会增加
  • 钩子方法:默认不做
    在这里插入图片描述
public class TemplateTest1 {
    public static void main(String[] args) {
        Medium medium = new Medium();
        MediumWell mediumWell = new MediumWell();

        medium.cook();
        mediumWell.cook();
    }
}
abstract class BeefSteak {
    final void cook() {
        heatingKettle();
        addOil();
        putBeef();
        fry();
        if (needBlackPepper()) {
            addBlackPepper();
        }
    }

    void heatingKettle() {
        System.out.println("热锅");
    }

    void addOil() {
        System.out.println("加入油");
    }

    void putBeef() {
        System.out.println("放入牛排");
    }


    boolean needBlackPepper() {
        return true;
    }

    abstract void fry();

    abstract void addBlackPepper();
}
class MediumWell extends BeefSteak {

    @Override
    void fry() {
        System.out.println("大火较长时间,七分熟");
    }

    @Override
    void addBlackPepper() {
        System.out.println("加入黑椒");
    }
}
class Medium extends BeefSteak {

    @Override
    void fry() {
        System.out.println("中火较短时间,五分熟");
    }

    @Override
    boolean needBlackPepper() {
        return false;
    }

    @Override
    void addBlackPepper() {

    }
}

命令模式

  • 请求发起者、请求执行者之间解耦
  • 空命令省去了判断的操作
  • 可能产生较多的命令类
角色
  • 调用者
  • 命令(抽象)
  • 接收者
    在这里插入图片描述
public class CommandTest1 {
    public static void main(String[] args) {
        Commander commander = new Commander();
        Air air = new Air();
        Army army = new Army();

        commander.getCommand(new ArmyAttack(army));
        commander.getCommand(new ArmyStop(army));
        commander.getCommand(new AirAttack(air));
        commander.getCommand(new AirStop(air));

        commander.command(0);
        commander.command(1);
        commander.command(2);
        commander.undo();
    }
}
class Commander {
    private ArrayList<Command> commands = new ArrayList<>();
    private ArrayList<Command> commandsHistory = new ArrayList<>();
    private int index = -2;

    public void getCommand(Command command) {
        commands.add(command);
    }

    public void command(int i) {
        Command command = commands.get(i);
        commands.get(i).execute();
        commandsHistory.add(command);
        index++;
    }

    public void undo() {
        if (index >= 0) {
            commandsHistory.remove(index + 1);
            commandsHistory.get(index--).execute();
        }
    }
}
class Army {
    public void attack() {
        System.out.println("陆军攻击");
    }

    public void stop() {
        System.out.println("陆军等待命令");
    }
}
class Air {
    public void attack() {
        System.out.println("空军攻击");
    }

    public void stop() {
        System.out.println("空军等待命令");
    }
}
interface Command {
    void execute();
}
class NoCommand implements Command {

    @Override
    public void execute() {
        //没有命令执行
    }
}
class ArmyAttack implements Command {
    private Army army;

    public ArmyAttack(Army army) {
        this.army = army;
    }

    @Override
    public void execute() {
        System.out.println("陆军执行攻击命令");
        army.attack();
    }


}
class ArmyStop implements Command {
    private Army army;

    public ArmyStop(Army army) {
        this.army = army;
    }

    @Override
    public void execute() {
        System.out.println("陆军执行等待命令");
        army.stop();
    }
}
class AirAttack implements Command {
    private Air air;

    public AirAttack(Air air) {
        this.air = air;
    }

    @Override
    public void execute() {
        System.out.println("空军执行攻击命令");
        air.attack();
    }

}
class AirStop implements Command {
    private Air air;

    public AirStop(Air air) {
        this.air = air;
    }

    @Override
    public void execute() {
        System.out.println("空军执行等待命令");
        air.stop();
    }
}

访问者模式

  • 符合单一职责原则、易扩展
  • 违反了依赖倒置原则,依赖了具体类
  • 在稳定的数据结构中使用
角色
  • 访问者
  • 接受者
  • 被访问的数据结构
    在这里插入图片描述
public class VisitorTest1 {
    public static void main(String[] args) {
        ObjectStructure objectStructure = new ObjectStructure();
        objectStructure.add(new CandidateA(12, 23));
        objectStructure.add(new CandidateB(23, 43));
        objectStructure.add(new CandidateB(78, 65));
        objectStructure.add(new CandidateB(34, 53));

        objectStructure.display(new ProfessionalSkillVisitor());
        objectStructure.display(new SortSkillVisitor());
    }
}
abstract class Candidate {
    abstract void accept(Visitor visitor);

    private int professionalSkill;
    private int SortSkill;

    public Candidate(int professionalSkill, int sortSkill) {
        this.professionalSkill = professionalSkill;
        SortSkill = sortSkill;
    }

    public int getProfessionalSkill() {
        return professionalSkill;
    }

    public int getSortSkill() {
        return SortSkill;
    }
}
class CandidateA extends Candidate {

    public CandidateA(int professionalSkill, int sortSkill) {
        super(professionalSkill, sortSkill);
    }

    @Override
    void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public void introduction() {
        System.out.print("求职:A职业 ");
    }
}
class CandidateB extends Candidate {

    public CandidateB(int professionalSkill, int sortSkill) {
        super(professionalSkill, sortSkill);
    }

    @Override
    void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public void introduction() {
        System.out.print("求职:B职业 ");
    }
}
interface Visitor {
    void visit(CandidateA candidateA);

    void visit(CandidateB candidateB);
}
class ProfessionalSkillVisitor implements Visitor {

    @Override
    public void visit(CandidateA candidateA) {
        System.out.print("专业技能访问者访问 ");
        candidateA.introduction();
        System.out.println("专业技能分值" + candidateA.getProfessionalSkill());
    }

    @Override
    public void visit(CandidateB candidateB) {
        System.out.print("专业技能访问者访问 ");
        candidateB.introduction();
        System.out.println("专业技能分值" + candidateB.getProfessionalSkill());
    }
}
class SortSkillVisitor implements Visitor {

    @Override
    public void visit(CandidateA candidateA) {
        System.out.print("软技能访问者访问 ");
        candidateA.introduction();
        System.out.println("软技能分值" + candidateA.getSortSkill());
    }

    @Override
    public void visit(CandidateB candidateB) {
        System.out.print("软技能访问者访问 ");
        candidateB.introduction();
        System.out.println("软技能分值" + candidateB.getSortSkill());
    }
}
class ObjectStructure {
    List<Candidate> candidates = new ArrayList<>();

    public void add(Candidate candidate) {
        candidates.add(candidate);
    }

    public void remove(Candidate candidate) {
        candidates.remove(candidate);
    }

    public void display(Visitor visitor) {
        for (Candidate candidate : candidates) {
            candidate.accept(visitor);
        }
    }
}

迭代器模式

  • 提供遍历集合元素的接口,对于不同的数据结构不需要了解底层,使用统一的方式遍历
角色
  • 集合(接口)
  • 迭代器(接口)
    在这里插入图片描述
public class IteratorTest1 {
    public static void main(String[] args) {
        List<Department> departments = new ArrayList<>();
        departments.add(new Design("设计部"));
        departments.add(new Design("开发部"));

        Company company = new Company(departments);

        company.printInfo();

        company.printDepartmentInfo(new Development("开发1部").getIterator());
    }
}
class Employee {
    private String name;

    public Employee(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }
}
class Company {
    List<Department> departments;

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

    public void printInfo() {
        for (Department department : departments) {
            System.out.println(department.getName());
            printDepartmentInfo(department.getIterator());
        }
    }

    public void printDepartmentInfo(Iterator<Employee> department) {
        while (department.hasNext()) {
            System.out.println(department.next());
        }
    }
}
interface Department {
    String getName();

    void add(Employee employee);

    void remove();

    Iterator<Employee> getIterator();
}
class Development implements Department {
    private String name;
    private Employee[] employees = new Employee[5];
    private int numberOfEmployee;

    public Development(String name) {
        this.name = name;
        add(new Employee("开发部员工1"));
        add(new Employee("开发部员工2"));
        add(new Employee("开发部员工3"));
        add(new Employee("开发部员工4"));

    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void add(Employee employee) {
        try {
            employees[numberOfEmployee++] = employee;
        } catch (ArrayIndexOutOfBoundsException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void remove() {

    }

    @Override
    public Iterator<Employee> getIterator() {
        return new IteratorForDepartment(employees);
    }
}
class Design implements Department {
    private String name;
    private List<Employee> employees = new ArrayList<>();

    public Design(String name) {
        this.name = name;
        employees.add(new Employee("设计部员工1"));
        employees.add(new Employee("设计部员工2"));
        employees.add(new Employee("设计部员工3"));
        employees.add(new Employee("设计部员工4"));
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void add(Employee employee) {
        employees.add(employee);
    }

    @Override
    public void remove() {

    }

    @Override
    public Iterator<Employee> getIterator() {
        return new IteratorForDesign(employees);
    }
}
class IteratorForDepartment implements Iterator<Employee> {
    private Employee[] employees;
    private int cursor = 0;

    public IteratorForDepartment(Employee[] employees) {
        this.employees = employees;
    }

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

    @Override
    public Employee next() {
        return employees[cursor++];
    }
}
class IteratorForDesign implements Iterator<Employee> {
    private int cursor;
    private List<Employee> employees;

    public IteratorForDesign(List<Employee> employees) {
        this.employees = employees;
    }

    @Override
    public boolean hasNext() {
        return cursor < employees.size();
    }

    @Override
    public Employee next() {
        return employees.get(cursor++);
    }
}

观察者模式

  • 对象的状态改变,依赖者可以得到通知并更新
  • 观察目标、观察者不可出现循环依赖
角色
  • 推送者(观察的目标)(Subject)
  • 观察者
    在这里插入图片描述
public class ObserverTest1 {
    public static void main(String[] args) {
        News news = new News();
        ObserverA observerA = new ObserverA();
        news.addObserver(observerA);
        news.addObserver(new ObserverB());

        news.setNew("消息1");

        news.removeObserver(observerA);

        news.setNew("最新消息");
    }
}
interface Subject {
    void addObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObservers();
}
class News implements Subject {
    private String latestNews;
    private List<Observer> observers = new ArrayList<>();

    public void setNew(String news) {
        latestNews = news;
        update();
    }

    private void update() {
        notifyObservers();
    }

    @Override
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(latestNews);
        }
    }
}
interface Observer {
    void update(String news);
}
class ObserverA implements Observer {
    private String news;

    @Override
    public void update(String news) {
        this.news = news;
        display();
    }

    private void display() {
        System.out.println("观察者A实例获得最新消息:" + news);
    }
}
class ObserverB implements Observer {
    private String news;

    @Override
    public void update(String news) {
        this.news = news;
        display();
    }

    private void display() {
        System.out.println("观察者B实例获得最新消息:" + news);
    }
}

中介者模式

  • 对象(类)之间直接与中介联系以跟其他对象(类)交互,达到松耦合目的
  • 中介封装了对象之间的交互
  • 对象之间存在比较复杂的引用关系使用
  • MVC模式,Controller就是中介
  • 中介的功能比较多,中介出现问题将影响到系统
角色
  • 中介(抽象类)
  • 同事(抽象类),指原本相互联系的多个对象
    在这里插入图片描述
public class MediatorTest1 {
    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();
        Seller seller = new Seller(mediator, "卖方");
        Buyer buyer1 = new Buyer(mediator, "买方1");
        Buyer buyer2 = new Buyer(mediator, "买方2");

        buyer1.sendMessage("你好。");
        seller.sendMessage("你好,请讲。");
    }
}
改进的可能
  • 案例相当于聊天室,一方发送消息,所以人都会收到消息
  • 可以改进成可以针对一方发生消息
abstract class Mediator {

    public abstract void addColleague(Colleague colleague);

    public abstract void reply(String source, String message);

}
class ConcreteMediator extends Mediator {
    private List<Colleague> colleagues = new ArrayList<>();

    @Override
    public void addColleague(Colleague colleague) {
        colleagues.add(colleague);
    }

    @Override
    public void reply(String source, String message) {
        for (Colleague colleague : colleagues) {
            String name = colleague.getName();
            if (name != source) {
                System.out.printf("[%s]收到来自[%s]的消息:%s%n", name, source, message);
            }
        }
    }
}
abstract class Colleague {
    private Mediator mediator;
    private String name;

    public Colleague(Mediator mediator, String name) {
        this.mediator = mediator;
        this.name = name;
    }

    public Mediator getMediator() {
        return mediator;
    }

    public String getName() {
        return name;
    }

    abstract public void sendMessage(String msg);

}
class Buyer extends Colleague {
    public Buyer(Mediator mediator, String name) {
        super(mediator, name);
        mediator.addColleague(this);
    }

    @Override
    public void sendMessage(String msg) {
        String name = super.getName();

        System.out.println(name + ":" + msg);
        getMediator().reply(name, msg);
    }
}
class Seller extends Colleague {
    public Seller(Mediator mediator, String name) {
        super(mediator, name);
        mediator.addColleague(this);
    }

    @Override
    public void sendMessage(String msg) {
        String name = super.getName();

        System.out.println(name + ":" + msg);
        getMediator().reply(name, msg);
    }
}

备忘录模式

  • 不破坏封装性的前提下,捕获对象的内部状态,以后可以恢复状态
  • 类的成员变量比较多会消耗较多资源
角色
  • 备忘录
  • 发起者
  • 守护者:维护备忘录
    在这里插入图片描述
public static void main(String[] args) {
        Caretaker caretaker = new Caretaker(5);
        ChessBoard chessBoard = new ChessBoard(5);

        chessBoard.display();
        caretaker.addMemento(new Memento(chessBoard.getBoard()));

        chessBoard.putIn(0, 0);
        caretaker.addMemento(new Memento(chessBoard.getBoard()));

        chessBoard.putIn(0, 1);
        caretaker.addMemento(new Memento(chessBoard.getBoard()));

        chessBoard.putIn(0, 2);

        chessBoard.reset(caretaker.getMemento());
        chessBoard.reset(caretaker.getMemento());
        chessBoard.reset(caretaker.getMemento());
        chessBoard.reset(caretaker.getMemento());
    }
public class ChessBoard {
    private char[][] board;

    public ChessBoard(int size) {
        board = new char[size][size];
        char[] chars;
        
        for (int i = 0; i < size; i++) {
            chars = board[i];
            for (int j = 0; j < size; j++) {
                chars[j] = 'O';
            }
        }
    }

    public char[][] getBoard() {
        int size = board.length;
        char[][] board = new char[size][size];
        for (int i = 0; i < size; i++) {
            System.arraycopy(this.board[i], 0, board[i], 0, size);
        }
        return board;
    }

    public void putIn(int x, int y) {
        if (board[x][y] == 'O') {
            board[x][y] = 'X';
            System.out.println("下棋");
            display();
        }
    }

    public void display() {
        for (int i = 0; i < board.length; i++) {
            System.out.println(Arrays.toString(board[i]));
        }
        System.out.println();

    }

    public void reset(Memento memento) {
        System.out.println("悔棋");
        board = memento.getMemento();
        display();
    }
}

需要注意成员变量为引用类型,创建备忘录时需要克隆、深拷贝

public class Memento {
    private char[][] board;

    public Memento(char[][] board) {
        this.board = board;
    }

    public char[][] getMemento() {
        return board;
    }
}
public class Caretaker {
    private ArrayDeque<Memento> queue = new ArrayDeque<>();
    private int capacity;

    public Caretaker(int capacity) {
        this.capacity = capacity;
    }

    public void addMemento(Memento memento) {
        if (queue.size() == capacity) {
            queue.removeFirst();
        }
        queue.add(memento);
    }

    public Memento getMemento() {
        Memento memento = null;
        try {
            memento = queue.removeLast();

        } catch (NoSuchElementException e) {
            e.printStackTrace();
        }
        return memento;
    }
}

解释器模式

  • 给定一语言,定义了它的文法的一种表示,定义解释器,用解释器解释语言中的句子
  • 遇到有些问题多次重复出现,而且有一定的相似性和规律性可使用
  • 如正则表达式
  • 会引起类膨胀
  • 采用递归调用
角色
  • 表达式(终结符、非终结符)
  • 环境类
    在这里插入图片描述
public class InterpreterTest {
    public static void main(String[] args) {
        HashMap<String, Integer> hashMap = new HashMap<>();
        System.out.println("定义运算符#,a#b运算为:a*b + b");

        hashMap.put("a", 3);
        hashMap.put("b", 4);
        System.out.println(hashMap.entrySet());

        Object[] objects = hashMap.keySet().toArray();
        String expr = String.format("%s#%s", objects[0], objects[1]);

        Content content = new Content(expr);
        System.out.println("表达式:" + expr + " 结果为:" + content.run(hashMap));
    }
}

public abstract class Expression {
    abstract public int interpret(HashMap<String, Integer> map);
}
public abstract class SymbolExpression extends Expression {
    protected Expression left;
    protected Expression right;

    public SymbolExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
}
public class OperatorExpression extends SymbolExpression {
    public OperatorExpression(Expression left, Expression right) {
        super(left, right);
    }

    @Override
    public int interpret(HashMap<String, Integer> map) {
        int num1 = left.interpret(map);
        int num2 = right.interpret(map);

        return num1 * num2 + num2;
    }
}
public class VarExpression extends Expression {
    String varName;

    public VarExpression(String varName) {
        this.varName = varName;
    }

    @Override
    public int interpret(HashMap<String, Integer> hashMap) {
        return hashMap.get(varName);
    }
}
public class Content {
    private Expression expression;

    public Content(String expression) {
        char[] chars = expression.toCharArray();

        Expression left = new VarExpression(String.valueOf(chars[0]));
        Expression right = new VarExpression(String.valueOf(chars[2]));
        this.expression = new OperatorExpression(left, right);
    }

    public int run(HashMap<String, Integer> map) {
        return expression.interpret(map);
    }
}

状态模式

  • 对象的内部状态发生变化时,允许改变其行为
  • 对于使用if-else的方法优化了许多
  • 会产生很多类(状态类)
角色
  • 环境
  • 状态(抽象类、接口)
    在这里插入图片描述
public class StateTest {
    public static void main(String[] args) {
        Order order = new Order();
        order.check();
        order.pay();
        order.receipt();
        order.complete();
        order.complete();//报错
    }
}
public interface OrderState {
    UnsupportedOperationException exception = new UnsupportedOperationException("非法操作");

    default void check(Order order) {
        throw exception;
    }

    default void pay(Order order) {
        throw exception;
    }

    default void receipt(Order order) {
        throw exception;
    }

    default void complete(Order order) {
        throw exception;
    }

    String getState();
}
class Generate implements OrderState {
    private String state = "待审核";

    @Override
    public void check(Order order) {
        order.setState(new PendingPayment());
    }

    public String getState() {
        return state;
    }

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

class PendingPayment implements OrderState {
    private String state = "待付款";

    @Override
    public void pay(Order order) {
        order.setState(new WaitDeliver());
    }

    public String getState() {
        return state;
    }

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

class WaitDeliver implements OrderState {
    private String state = "待发货";

    @Override
    public void receipt(Order order) {
        order.setState(new WaitConfirm());
    }

    public String getState() {
        return state;
    }

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

class WaitConfirm implements OrderState {
    private String state = "待收货";

    @Override
    public void complete(Order order) {
        order.setState(new Competed());
    }

    public String getState() {
        return state;
    }

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

class Competed implements OrderState {
    private String state = "已完成";

    @Override
    public String getState() {
        return state;
    }
}
public class Order {
    private OrderState state;

    public Order() {
        state = new Generate();
    }

    public void check() {
        System.out.print("当前订单状态为:" + state.getState() + "----→");
        state.check(this);
        printState();
    }

    public void pay() {
        System.out.print("当前订单状态为:" + state.getState() + "----→");
        state.pay(this);
        printState();
    }

    public void receipt() {
        System.out.print("当前订单状态为:" + state.getState() + "----→");
        state.receipt(this);
        printState();
    }

    public void complete() {
        System.out.print("当前订单状态为:" + state.getState() + "----→");
        state.complete(this);
        printState();
    }

    public void printState() {
        System.out.println(state.getState());
    }

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

策略模式

  • 使用聚合、组合而不是继承
  • 算法和使用算法的客户独立
  • 避免了多重判断语句
  • 算法可以替换
  • 多个类中的只有行为不一样时,可以使用
  • 每增加一个策略都将增加一个类
角色
  • 策略类(接口,多个)
  • 环境类(使用策略)
    在这里插入图片描述
public class StrategyTest {
    public static void main(String[] args) {
        Student student = new Student(new Study());
        student.doSomething();

        student.setStrategy(new Fitness());
        student.doSomething();

        student.setStrategy(new Game());
        student.doSomething();
    }
}
public interface Strategy {
    void doSomething();
}
class Study implements Strategy {

    @Override
    public void doSomething() {
        System.out.println("学习。。。");
    }
}

class Fitness implements Strategy {

    @Override
    public void doSomething() {
        System.out.println("健身。。。");
    }
}

class Game implements Strategy {

    @Override
    public void doSomething() {
        System.out.println("游戏。。。");
    }
}
public class Student {
    private Strategy strategy;

    public Student() {
    }

    public Student(Strategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public void doSomething() {
        strategy.doSomething();
    }
}

职责链模式

  • 多个对象可以处理请求,但处理的时间不确定
  • 处理消息需要过滤多道
  • 发送者不需要了解将传递过程,发送者和处理者解耦
  • 避免使用过的判断语句
  • 需要为处理者设置下一个处理者
  • 不能保证处理一定会被处理
角色
  • 处理者(抽象)
  • 客户
    在这里插入图片描述
public class ChainOfResponsibilityTest {
    public static void main(String[] args) {
        Handler instructor = new Instructor("辅导员");
        Handler collegeDean = new CollegeDean("院长");
        Handler secretary = new Secretary("书记");

        instructor.setNextHandler(collegeDean);
        collegeDean.setNextHandler(secretary);
        secretary.setNextHandler(instructor);//将链设置成环
        instructor.process(7);
        secretary.process(1);
    }
}
public abstract class Handler {
    protected String name;
    protected Handler nextHandler;

    public Handler(String name) {
        this.name = name;
    }

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void process(int days);
}

public class Instructor extends Handler {
    public Instructor(String name) {
        super(name);
    }

    @Override
    public void process(int days) {
        if (days <= 0 || days > 30) {
            System.out.printf("不允许请假%d%n", days);
        } else if (days <= 3) {
            System.out.printf("%s批准申请%d天假%n", name, days);
        } else {
            nextHandler.process(days);
        }
    }
}

public class CollegeDean extends Handler {
    public CollegeDean(String name) {
        super(name);
    }

    @Override
    public void process(int days) {
        if (days > 4 && days <= 7) {
            System.out.printf("%s批准申请%d天假%n", name, days);
        } else {
            nextHandler.process(days);
        }
    }
}
public class Secretary extends Handler {
    public Secretary(String name) {
        super(name);
    }

    @Override
    public void process(int days) {
        if (days > 7 && days < 14) {
            System.out.printf("%s批准申请%d天假%n", name, days);
        } else if (nextHandler != null) {
            nextHandler.process(days);
        }
    }
}

参考

设计模式六大原则
设计模式视频

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值