设计模式

创造型、结构型、行为型

创建型:

1、(类)工厂方法(Factory Method)

意图

定义一个用于创建对象的接口,让子类决定实例化哪一个类。使一个类的实例化延迟到了子类

适用性

1.当一个类不知道它所必须创建的对象的时候

2.当一个类希望由它的子类来指定它所创建的对象的时候

3.当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一帮助子类是代理者这一信息局部化的时候

实现代码

package com.yhw.factoryPattern;
//工厂方法模式
public class FactoryMethod {
    public static void main(String[] args){
    Factory factoryA = new FactoryA();
    //类名 对象名 = new 子类();
    Factory factoryB = new FactoryB();

    Product productA = factoryA.createProduct();
    ();

    Product productB = factoryB.createProduct();
    ();
    }
}
interface Factory {

    public Product createProduct();
}

class FactoryA implements Factory{
    public Product createProduct(){
        return new ProductA();
    }
}

class FactoryB implements Factory{

     @Override
     public Product createProduct() {
         return new ProductB();
     }
 }

 interface Product{
    public void info();
}

class ProductA implements Product{
    public void info(){
        System.out.println("商品信息:A");
    }
}

class ProductB implements Product{

    @Override
    public void info(){
        System.out.println("商品信息:B");
    }
}

简单工厂模式实现代码

package com.yhw.simpleFactory;
//简单工厂模式
public class SimpleFactory {
    public static void main(String[] args) {
       Product productA = Factory.CreateProduct("A");
       Product productB = Factory.CreateProduct("B");
       ();
       ();
    }
}
    class Factory {
        public static Product CreateProduct(String type){
            Product product = null;
            switch(type){
                case "A":
                    product = new ProductA();
                    break;
                case "B":
                    product = new ProductB();
                    break;
                default:
                    System.out.println("本店没有此类产品");
            }
            return product;
        }
    }
    abstract class Product{
        public abstract void info();
    }

    class ProductA extends Product{

        @Override
        public void info() {
            System.out.println("产品信息为:A");
        }
    }
    class ProductB extends Product{

        @Override
        public void info() {
            System.out.println("产品信息为:B");
        }
    }

2、抽象工厂(Abstract Factory)

意图

提供一个创建一系列相关或相互依赖对象接口,而无须指定他们具体的类

适用性

1.一个系统要独立于它的产品创建、组合和表示时

2.一个系统要由多个产品系列中的一个来配置时

3.当要强调一系列相关产品对象的设计以便于进行联合使用时

4.当提供一个产品类库,只想显示它们的接口而不是实现时

实现代码

package com.yhw.AbstractFactory;

public class Factory {

    public static void main (String[] args ){

        abstractFactory Factory1 = new Factory1();
        abstractFactory Factory2 = new Factory2();

        ProductA productA = Factory1.CreateProductA();
        ();
        ProductB productB = Factory1.CreateProductB();
        ();

    }
}//抽象工厂模式
interface abstractFactory{
    public ProductA CreateProductA();
    public ProductB CreateProductB();
}

class Factory1 implements abstractFactory{

    @Override
    public ProductA CreateProductA() {
        return new ProductA1();
    }

    @Override
    public ProductB CreateProductB() {
        return new ProductB1();
    }
}
class Factory2 implements abstractFactory{

    @Override
    public ProductA CreateProductA() {
        return new ProductA2();
    }

    @Override
    public ProductB CreateProductB() {
        return new ProductB2();
    }
}

interface ProductA{
    public void info();
}
class ProductA1 implements ProductA{

    @Override
    public void info() {
        System.out.println("产品信息:A2");
    }
}
class ProductA2 implements ProductA{

    @Override
    public void info() {
        System.out.println("产品信息:A2");
    }
}
interface ProductB{
    public void info();
}
class ProductB1 implements ProductB{
    @Override
    public void info() {
        System.out.println("产品信息:B1");
    }
}
class ProductB2 implements ProductB{

    @Override
    public void info() {
        System.out.println("产品信息:B2");
    }
}

3、生成器(Builder)

意图

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

适用性

1.当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装饰方式时

2.当构造过程必须允许被构造的对象有不同的表示时

实现代码

package com.yhw.builder;
//生成器模式
public class Builder {
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        PizzaBuilder hawaiian_pizzaBuilder = new HawaiianPizzaBuilder();
        waiter.setPizzaBuilder(hawaiian_pizzaBuilder);
        waiter.construct();

        System.out.println("pizza:"+waiter.getPizza());

        PizzaBuilder spicy_pizzaBuilder = new SpicyPizzaBuilder();
        waiter.setPizzaBuilder(spicy_pizzaBuilder);
        waiter.construct();

        System.out.println("pizza:"+waiter.getPizza());
    }
}

class Pizza{
    private String parts;
    public void setParts(String parts){this.parts = parts;}
    public String toString(){return this.parts;}
}

abstract class PizzaBuilder{
    protected Pizza pizza;
    public Pizza getPizza(){return pizza;}
    public void createNewPizza(){pizza = new Pizza();}

    public abstract void buildParts();
}
class HawaiianPizzaBuilder extends PizzaBuilder{
    public void buildParts(){pizza.setParts("cross + mild + ham&pineapple");}
}
class SpicyPizzaBuilder extends PizzaBuilder{
    public void buildParts(){pizza.setParts("panbaked + hot + pepperoni&salami");}
}
class Waiter{
    private PizzaBuilder pizzaBuilder;
    public void setPizzaBuilder(PizzaBuilder pizzaBuilder){//设置构建器
        this.pizzaBuilder = pizzaBuilder;
    }
    public Pizza getPizza(){return pizzaBuilder.getPizza();}
    public void construct(){//生成pizza
        pizzaBuilder.createNewPizza();
        pizzaBuilder.buildParts();
    }

}

4、原型(Prototype)

意图

用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象

适用性

1.当一个系统应该独立于它的产品创建、构成和表示时

2.当要实例化的类是在运行时刻指定时,例如,通过动态装载

3.为避免创建一个与产品类层次平行的工厂类层次时

4.当一个类的实例化只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手 工实例化该类更方便

实现代码

package com.yhw.prototype;
//原型模式
public class Prototype {
    public static void main(String[] args) {
        Resume a = new Resume("张三");
        a.SetPersonInfo("男","29");
        a.SetWorkExperience("1999 - 2006","xxx");
        Resume b = (Resume) a.Clone();
//        b.SetWorkExperience("2006 - 2010","yyy");

        System.out.println(a.getWork().getWorkDate()+" "+a.getWork().getCompany());
        System.out.println(b.getWork().getWorkDate()+" "+b.getWork().getCompany());

    }
}
interface Cloneable{
    Object Clone ();
}
class WorkExperience implements Cloneable{
    private String workDate;
    private String company;

   void SetWorkDate (String workDate){this.workDate = workDate;}
   void SetCompany (String company){this.company = company;}

    public String getWorkDate() {
        return workDate;
    }

    public String getCompany() {
        return company;
    }

    @Override
    public Object Clone(){
        WorkExperience obj = new WorkExperience();
        obj.company = this.company;
        obj.workDate = this.workDate;
        return obj;
    }
}
class Resume implements Cloneable{
    private String name;
    private String sex;
    private String age;
    private WorkExperience work;

    public WorkExperience getWork() {
        return work;
    }

    public Resume(String name) {
         = name;
        work = new WorkExperience();
    }
    private Resume(WorkExperience work){
        this.work = (WorkExperience) work.Clone();
    }

    public void SetPersonInfo(String sex,String age){
        this.sex = sex;
        this.age = age;
    }

    public void SetWorkExperience(String workDate , String company){
        this.work.SetWorkDate(workDate);
        this.work.SetCompany(company);
    }

    public Object Clone(){
        Resume obj = new Resume(this.work);
        return obj;
    }
}

5、单例(Singleton)

意图

保证一个类仅有一个实例,并提供一个访问它的全局访问点

适用性

1.当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时

2.当这个唯一实例应该时通过子类化可扩展的,并且客户无须更改代码就能使用一个扩展的实例时

实现代码

package com.yhw.singletonPattern;
//单例模式
public class SingletonPattern {
    public static void main (String[] args){
        Singleton instance = Singleton.getInstance();
        instance.setNumber(2022);
        System.out.println(instance.getNumber());
    }
}
class Singleton{
    private int number ;

    public void setNumber(int number) {
        this.number = number;
    }

    public int getNumber() {
        return number;
    }

    private static Singleton instance = new Singleton();
    private Singleton(){}

    public static Singleton getInstance(){
        return instance;
    }
}

结构型

1、适配器(Adapter)

意图

将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

适用性

1.想使用一个已经存在的类,而它的接口不符合要求

2.想创建一个可以服用的类,该类可以与其他不相关的类或者不可预见的类(即那些接口可能不一定兼容的类)协同工 作

3.想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配他们的接口。对象适配器可以适配它的父类接口

实现代码

package com.yhw.adapterPattern;
//适配器模式
public class AdapterPattern {
    public static void main (String[] args){
        USB usb = new Adapter();
        usb.Request();
    }
}

class USB {
    public void Request(){
        System.out.println("USB数据线");
    }
}
class Adapter extends USB{
    private TypeC typeC = new TypeC();
    @Override
    public void Request() {
        typeC.SpecificRequest();
    }
}

class TypeC{
    public void SpecificRequest(){
        System.out.println("Tape-C数据线");
    }
}

2、桥接(Bridge)

意图

将抽象部分与其实现部分分离,使它们都可以独立变化

适用性

1.不希望在抽象和它的实现部分之间有一个固定的关系

2.类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充

3.对一个抽象的实现部分修改应对客户不产生影响,即客户代码不必重新编译

4.有许多类要生成的类层次结构

实现代码

package com.yhw.bridgePattern;
//桥接模式
public class BridgePattern {
    public static void main(String[] args) {
        Product productA = new ProductA();
        Product productB = new ProductB();
        Color Red = new Red();
        Color Blue = new Blue();

        productA.setName("productA");
        productA.setColor(Red);
        productA.Operation();

        productB.setName("productB");
        productB.setColor(Blue);
        productB.Operation();
    }
}
abstract class Product{
    private String name;
    protected Color color;

    public void setName(String name){
         = name;
    }
    public String getName(){
        return name;
    }

    public void setColor (Color color){
        this.color = color;
    }
    public abstract void Operation();
}//抽象的产品类

class ProductA extends Product{

    @Override
    public void Operation() {
        color.OperationImp(this.getName());
    }
}//产品类
class ProductB extends Product{

    @Override
    public void Operation() {
        color.OperationImp(this.getName());
    }
}

interface Color{
    void OperationImp(String name);
}//颜色接口

class Red implements Color {
    @Override
    public void OperationImp(String name){
        System.out.println(name+": 红色");
    }
}//具体的实现类
class Blue implements Color {
    @Override
    public void OperationImp(String name){
        System.out.println(name+": 蓝色");
    }
}

3、组合(Composite)

意图

将对象组合成树型结构以表示“部分—整体”的层次结构。Conposite使得用户对单个对象和组合对象的使用具有一致性。

适用性

1.想表示对象的部分—整体层次结构。

2.希望用户忽略组合对象与单个对象的不同。用户将统一的使用组合结构中的所有对象。

实现代码

package com.yhw.composite;
import java.util.*;
//组合模式
public class Composite {
    public static void main (String[] args){
        AbstractFile root = new Folder("root");

        AbstractFile folderA = new Folder("folderA");
        AbstractFile fileB = new File("fileB");
        AbstractFile fileC = new File("fileC");
        AbstractFile fileD = new File("fileD");

        System.out.println(root.Add(folderA));
        System.out.println(root.Add(fileB));
        folderA.Add(fileC);
        folderA.Add(fileD);
        System.out.println("-------------------------");

        print(root);

//        System.out.println(root.Remove(folderA));
//        System.out.println(root.Remove(fileB));
    }
    static void print(AbstractFile file){
        file.printName();
        List<AbstractFile> Children = file.GetChildren();

        while (Children == null)return;
        for (AbstractFile children : Children){
//            children.printName();//打印出在此文件夹中的子文件
            print(children);//打印此文件夹中的所有文件,前序遍历
        }
    }
}
abstract class AbstractFile{
    protected String name;

    public void printName(){
        System.out.println(name);
    }
    public abstract boolean Add(AbstractFile file);
    public abstract boolean Remove(AbstractFile file);
    public abstract List<AbstractFile> GetChildren();
}
class Folder extends AbstractFile{
    private List<AbstractFile> childrenList = new ArrayList<AbstractFile>();

    public Folder (String name){
         = name;
    }

    @Override
    public boolean Add(AbstractFile file) {
        return childrenList.add(file);
    }

    @Override
    public boolean Remove(AbstractFile file) {
        return childrenList.remove(file);
    }

    @Override
    public List<AbstractFile> GetChildren() {

        return childrenList;
    }
}
class File extends AbstractFile{
    public File (String name){
         = name;
    }

    @Override
    public boolean Add(AbstractFile file) {
        return false;
    }

    @Override
    public boolean Remove(AbstractFile file) {
        return false;
    }

    @Override
    public List<AbstractFile> GetChildren() {
        return null;
    }
}

4、装饰器(Decorator)

意图

动态的给一个对象添加一些额外的职责。就增强功能而言,Decorator模式比生成子模式更加

适用性

1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

2.处理那些可以撤回的职责。

3.当不能采用生成子类的方式进行扩张时。

实现代码

package com.yhw.decoratorPattern;
//装饰器模式
public class DecoratorPattern {
    public static void main(String[] args) {
        Person lbw = new Student("lbw");
//        lbw.Operation();
//        System.out.println("\n===================");
        lbw = new ConcreteDecoratorA(lbw);
//        lbw.Operation();
//        System.out.println("\n================");
        lbw = new ConcreteDecoratorB(lbw);
        lbw.Operation();
        System.out.println("==============");

        Person lisi = new ConcreteDecoratorB(new ConcreteDecoratorA(new Student("lisi")));
        //第二种写法(对象链),直接套起来写
    }
}
abstract class Person{
    protected String name;

    public abstract void Operation();//职责

}
class Student extends Person{

    public Student(String name) {
         = name;
    }

    @Override
    public void Operation() {
        System.out.print(name+"的职责:学习 ");
    }
}
abstract class Decorator extends Person{
    protected Person person;

}
class ConcreteDecoratorA extends Decorator{
    public ConcreteDecoratorA(Person person){
        this.person = person;
    }
    @Override
    public void Operation() {
        person.Operation();
        System.out.print("写作业 ");
    }
}
class ConcreteDecoratorB extends Decorator{
    public ConcreteDecoratorB(Person person){
        this.person = person;
    }
    @Override
    public void Operation() {
        person.Operation();
        System.out.print("看电视 ");
    }
}

5、外观(Facade)

意图

为子系统中的一组接口提供一个一致的界面,Facade定义了一个高层接口,这个接口使得这一子系统更加容易使用。

适用性

1.要为一个复杂子系统提供一个简单接口时。

2.客户程序与抽象类的实现部分之间存在着很大的依赖性。

3.当需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点。

实现代码

package com.yhw.FacadePattern;
//外观模式
public class FacadePattern {
    public static void main (String[] args){
        Facade facade = new Facade();
        facade.methodA();
        facade.methodB();
    }
}
class Facade {
    SubSystemOne subSystemOne;
    SubSystemTwo subSystemTwo;
    SubSystemThree subSystemThree;

    public Facade(){
        subSystemOne = new SubSystemOne();
        subSystemTwo = new SubSystemTwo();
        subSystemThree = new SubSystemThree();
    }
    public void methodA(){
        subSystemOne.methodOne();
    }
    public void methodB(){
        subSystemTwo.methodTwo();
    }
    public void methodC(){
        subSystemThree.methodThree();
    }
}


class SubSystemOne {
    public void methodOne(){
        System.out.println("第一个方案");
    }
}
class SubSystemTwo {
    public void methodTwo(){
        System.out.println("第二个方案");
    }
}
class SubSystemThree {
    public void methodThree(){
        System.out.println("第三个方案");
    }
}

6、享元(Flyweight)

意图

运用共享技术有效地支持大量细粒度的对象

适用性

1.一个应用程序使用了大量的对象。

2.完全由于使用大量的对象,造成很大的存储开销。

3.对象的大多数状态都可变为外部状态。(外部:易变 、 内部:不易变)

4.如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。

实现代码

1.画圆案例

package com.yhw.flyweightPattern2;
import java.util.*;
//享元模式
public class Flyweight {
    public static void main(String[] args) {
        ShapeFactory shapeFactory = new ShapeFactory();
        Random random = new Random();
        String[] colors ={"white", "black", "green" , "red" , "blue"};

        for (int i = 1; i <= 10; i++) {
            int x = random.nextInt(colors.length);//[0~4]
            Shape shape = shapeFactory.getShape(colors[x]);

            System.out.print("第"+ i +"个圆:");
            shape.draw(random.nextInt(2022), random.nextInt(115) );
        }
    }
}

class ShapeFactory{
    private Map<String , Shape> map = new HashMap<String , Shape>();

    public Shape getShape(String key){
//        if(map.containsKey(key)){
//            return map.get(key);
//        }
//        else {
//            Shape shape = new Circle(key);
//            map.put(key , shape);
//            System.out.println("create color:" + key +" circle");
//            return shape;
//
//            //return map.get(key);
//        }//没有简化版
        if(!map.containsKey(key)){
            map.put(key ,new Circle(key));
            System.out.println("create color: " + key +" circle");
        } return map.get(key);//简化版
    }
}
abstract class Shape{
    protected String color;

    public abstract void draw(int x, int y);
}

class Circle extends Shape{
    protected String color;
    public Circle(String color){
        this.color = color;
    }

    @Override
    public void draw(int x, int y) {
        System.out.println("draw a color" + color +"Circle X:" + x +" Y:" + y);
    }
}

2.下棋案例

package com.yhw.flyweightPattern1;
//享元模式
public class Flyweight {
    public static void main(String[] args) {
        PieceFactory pieceFactory = new PieceFactory();
        Piece whitePiece1 = pieceFactory.getPiece(0);
        Piece whitePiece2 = pieceFactory.getPiece(0);
        Piece whitePiece3 = pieceFactory.getPiece(0);
        Piece whitePiece4 = pieceFactory.getPiece(0);//都是同一个对象,只是draw的位置不同
        whitePiece1.draw(20,30);

    }
}
class PieceFactory{
    private Piece[] pieces = {new WhitePiece(), new BlackPiece()};
    public Piece getPiece (int key){
        if (key == 0)return pieces[0];
        else return pieces[1];
    }
}//创建棋子的工厂

abstract class Piece{
    protected String color;
    public abstract void draw(int x, int y);
}
class WhitePiece extends Piece{
    public WhitePiece(){
        this.color = "white";
    }

    @Override
    public void draw(int x, int y) {
        System.out.println("draw a color" + color + "piece x:" + x +"y:" +y);
    }
}
class BlackPiece extends Piece{
    public BlackPiece(){
        this.color = "black";
    }

    @Override
    public void draw(int x, int y) {
        System.out.println("draw a color" + color + "piece x:" + x +"y:" +y);
    }
}

7、代理(Proxy)

意图

为其他对象提供一种代理以控制对这个对象的访问

适用性

适用于在需要比较通用和复杂的对象指针代替简单的指针的时候

1.远程代理:为一个对象在不同地址空间提供局部代表

2.虚代理:根据需要创建开销很大的对象

3.保护代理:控制对原始对象的访问,用于对象应该有不同的访问权限的时候

4.智能引用:取代了简单的指针他在访问对象时执行一些附加的操作

实现代码

package com.yhw.proxyPattern;
//代理模式
public class ProxyPattern {
    public static void main(String[] args) {
        RealSubject realSubject = new RealSubject();
        Subject proxy = new Proxy(realSubject);
        proxy.Buy();
    }
}
    interface Subject {
        void Buy();
    }

    class Proxy implements Subject {
        protected RealSubject realSubject;

        public Proxy(RealSubject realSubject) {
            this.realSubject = realSubject;
        }

        @Override
        public void Buy() {
            System.out.println("办理购买前的手续");
            realSubject.Buy();
            System.out.println("办理购买后的手续");
        }
    }

    class RealSubject implements Subject {

        @Override
        public void Buy() {
            System.out.println("付钱");
        }
    }

行为型

1、责任链(Chain of Responsibility)

意图

使多个对象都有机会处理请求,从而避免发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

适用性

1.有多个对象可以处理一个请求,哪个对象处理该请求运行时自动确定

2.想在不明确指定接收者的情况下向多个对象中的一个提交一个请求

3.可处理一个请求的对象集合应被动态指定

实现代码

package com.yhw.responsibility;
//责任链模式
public class Responsibility {
    public static void main(String[] args) {
        Handler fudaoyuan = new FuDaoYuan();
        Handler yuanzhang = new YuanZhang();
        Handler xiaozhang = new XiaoZhang();
        fudaoyuan.setNext(yuanzhang);
        yuanzhang.setNext(xiaozhang);

        fudaoyuan.HandlerRequest(18);
    }
}
abstract class Handler{
    protected Handler next;
    public void setNext(Handler next){
        this.next = next;
    }

    public abstract void HandlerRequest(int request);
}
class FuDaoYuan extends Handler{

    @Override
    public void HandlerRequest(int request) {
        if (request <= 7) System.out.println("辅导员审批通过!");
        else {
            if (next != null){
                next.HandlerRequest(request);
            }else System.out.println("无法审批");
        }
    }//<=7天辅导员可以批
}
class YuanZhang extends Handler{

    @Override
    public void HandlerRequest(int request) {
        if (request <= 15) System.out.println("院长审批通过!");
        else {
            if (next != null){
                next.HandlerRequest(request);
            }else System.out.println("无法审批");
        }
    }//<=15天院长可以批
}
class XiaoZhang extends Handler{

    @Override
    public void HandlerRequest(int request) {
        if (request <= 30) System.out.println("校长审批通过!");
        else {
            if (next != null){
                next.HandlerRequest(request);
            }else System.out.println("无法审批");
        }
    }//<=30天校长可以批
}

2、命令(Command)

意图

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

适用性

1.抽象出待执行的动作以参数化某个对象

2.在不同的时刻指定、排队和执行操作

3.支持取消操作

4.支持修改日志

5.用构建在原语操作上的高层操作构建一个系统

实现代码

package com.yhw.commandPattern;
//命令模式
public class CommandPattern {
    public static void main(String[] args) {
        Tv tv = new Tv();
        Command on = new OnCommand(tv);
        Command off = new OffCommand(tv);
        Invoker invoker = new Invoker();
        invoker.setCommand(on);
        invoker.call();
        invoker.setCommand(off);
        invoker.call();
    }
}
interface Command{
    public void Execute();
}
class Invoker{//遥控器
    private Command command;//请求
    public void setCommand(Command command){
        this.command = command;
    }//设置请求者的请求
    public void call(){
        command.Execute();
    }
}
class OnCommand implements Command{
    private Tv tv;
    public OnCommand(Tv tv){
         = tv;
    }
    @Override
    public void Execute() {
        tv.up();
    }
}
class OffCommand implements Command{
    private Tv tv;
    public OffCommand(Tv tv){
         = tv;
    }
    @Override
    public void Execute() {
        tv.off();
    }
}
class Tv{
    public void up(){
        System.out.println("电视机开机了");
    } public void off(){
        System.out.println("电视机关机了");
    }
}

3、(类)解释器(Interpreter)

意图

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

适用性

适用于当有一个语言需要解释执行,并且可以将该语言中的句子表示为一个抽象语法树时,以下效果最好:

1.该语法简单

2.效率不是一个关键问题

实现代码

package com.yhw.interpreterPattern;

import java.util.HashSet;
import java.util.Set;
//解释器模式
public class InterpreterPattern {
    public static void main(String[] args) {
        Context context = new Context();

        context.check("A区的开发人员");
        context.check("B区的测试人员");
        context.check("C区的调试人员");
        System.out.println("========");
        context.check("D区的开发人员");
        context.check("A区的摆烂人员");
        context.check("D区的摆烂人员");
    }
}
class Context{
    private String[] regions = {"A区","B区","C区"};
    private String[] persons = {"开发人员","测试人员","调试人员"};

    private NonterminalExpression nonterminalExpression;

    public Context(){
        TerminalExpression region = new TerminalExpression(regions);
        TerminalExpression person = new TerminalExpression(persons);
        nonterminalExpression = new NonterminalExpression(region,person);
    }

    public void check(String info){
        boolean bool = nonterminalExpression.Interpreter(info);
        if (bool) System.out.println("识别成功");
        else System.out.println("识别失败");
    }

}
interface Expression{
    public boolean Interpreter(String into);
}
class TerminalExpression implements Expression{
    private Set<String> set = new HashSet<String>();

    public TerminalExpression(String[] data){
        //for(被遍历对象类型 对象名 :遍历对象)
        for(String str : data){
            set.add(str);
        }
    }
    @Override
    public boolean Interpreter(String into) {
        return set.contains(into);
    }
}
class NonterminalExpression implements  Expression{
    private TerminalExpression region;
    private TerminalExpression person;

    public NonterminalExpression(TerminalExpression region , TerminalExpression person){
        this.region = region;
        this.person = person;
    }
    @Override
    public boolean Interpreter(String info) {
        String[] str = info.split("的");
        //A区的开发人员--> str = {"A区" ,"开发人员"}
        return region.Interpreter(str[0]) && person.Interpreter(str[1]);

    }
}

4、迭代器(Iterator)

意图

提供一种方法顺序访问一个聚合对象中的各个元素,且不需要暴露该对象的内部表示。

适用性

1.访问一个聚合对象的内容而无须暴露它的内部表示

2.支持对聚合对象的多种遍历

3.为遍历不同的聚合结构提供一个统一的接口

实现代码

package com.yhw.iteratorPattern1;
import java.util.*;
//迭代器模式
public class IteratorPattern1 {//使用迭代器模式访问聚合对象

    public static void main(String[] args) {
        BookAggregate bookAggregate = new BookAggregate();


        String[] Books = {"数据结构", "操作系统", "计算机组成原理", "计算机网络", "数据库原理"};
        double[] prices = {20.5, 30.5, 33.3, 40.5, 50.0};
        for (int i = 0; i <= 4; i++) {
            bookAggregate.Add(new Book(Books[i],prices[i]));
        }

        Iterator bookIterator = bookAggregate.CreateIterator();
        while (bookIterator.hasNext()){
            Book book =(Book) bookIterator.next();
            System.out.println(book.getName()+" "+book.getPrice());
        }
    }
}
interface Iterator{
        public boolean hasNext();
        public Object next();
}//自己创建的迭代器,不是java自带的

class BookIterator implements Iterator{
    private int index;
    private BookAggregate bookAggregate;

    public BookIterator(BookAggregate bookAggregate){
        this.index = 0;
        this.bookAggregate = bookAggregate;
    }
    @Override
    public boolean hasNext() {
        if (index < bookAggregate.getSize())return true;
        else return false;
    }

    @Override
    public Object next() {
        Object obj = bookAggregate.getBook(index);
        index++;
        return obj;
    }
}

interface Aggregate{
    public Iterator CreateIterator();
}
class BookAggregate implements Aggregate{
    List<Book> booklist = new ArrayList<>();

    public void Add(Book book){
        booklist.add(book);
    }
    public Book getBook(int index){
        return booklist.get(index);
    }
    public int getSize(){
        return booklist.size();
    }

    @Override
    public Iterator CreateIterator() {
        return new BookIterator(this);
    }
}

class Book {
        private String name;
        private double price;

        public Book(String name, double price) {
             = name;
            this.price = price;
        }

        public String getName() {
            return name;
        }

        public double getPrice() {
            return price;
        }
    }

5、中介者(Mediator)

意图

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示的相互引用,从而使其耦合松散,而且可以独立的改变他们之间的交互。

适用性

1.一组对象以定义良好但是复杂的方式进行通信,产生的相互依赖关系结构混乱且难以理解。

2.一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。

3.想定制一个分布在多个类中的行为,而又不想生成太多子类。

实现代码

package com.yhw.mediatorPattern;
//中介者模式
public class MediatorPattern {
    public static void main(String[] args) {
        ConcreteMediator mediator = new ConcreteMediator();

        Colleague1 colleague1 = new Colleague1(mediator);
        Colleague2 colleague2 = new Colleague2(mediator);

        mediator.setColleague1(colleague1);
        mediator.setColleague2(colleague2);

        colleague1.sendMessage("你干嘛~欸哟");
        colleague2.sendMessage("唱 跳 rap 篮球");
    }
}

abstract class Colleague{
    protected Mediator mediator;

}
class Colleague1 extends Colleague{
    public Colleague1(Mediator mediator){
        this.mediator = mediator;
    }
    public void sendMessage(String message){
        mediator.sendMessage(message,this);
    }
    public void Notify(String message){
        System.out.println("同事1收到消息 "+message);
    }
}
class Colleague2 extends Colleague{
    public Colleague2(Mediator mediator){
        this.mediator = mediator;
    }
    public void sendMessage(String message){
        mediator.sendMessage(message,this);
    }
    public void Notify(String message){
        System.out.println("同事2收到消息 "+message);
    }
}
abstract class Mediator{
    public abstract void sendMessage(String message , Colleague colleague);

}
class ConcreteMediator extends Mediator{
    private Colleague1 colleague1;
    private Colleague2 colleague2;

    public void setColleague1(Colleague1 colleague1){
        this.colleague1 = colleague1;
    }
    public void setColleague2(Colleague2 colleague2){
        this.colleague2 = colleague2;
    }
    @Override
    public void sendMessage(String message, Colleague colleague) {
        if (colleague == colleague1){
            //让同事2收到消息
            colleague2.Notify(message);
        }else{
            //让同事1收到消息
            colleague1.Notify(message);
        }
    }
}

6、备忘录(Memento)

意图

在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态

适用性

1.必须保存一个对象在某一时刻的(部分)状态,这样以后需要时才能恢复到先前的状态

2. 如果一个用接口来让其他对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性

实现代码

package com.yhw.mementoPattern;

import java.util.ArrayList;
import java.util.List;
//备忘录模式
public class MementoPattern {
    public static void main(String[] args) {
        Caretaker caretaker = new Caretaker();
        Originator originator = new Originator();

        originator.setState("1024");
        Memento memento1 = originator.createMemento();
        caretaker.addMemento(memento1);

        originator.setState("2048");
        Memento memento2 = originator.createMemento();
        caretaker.addMemento(memento2);

        originator.setState("4096");
        Memento memento3 = originator.createMemento();
        caretaker.addMemento(memento3);

        System.out.println(originator.getState());
        caretaker.showMemento();

        Memento memento0 = caretaker.getMemento(2);
        originator.setMemento(memento0);
        System.out.println(originator.getState());
    }

}
class Originator{
    private String state;

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

    public Memento createMemento(){
        return new Memento(state);
    }
    public void setMemento(Memento memento){
        state = memento.getState();
    }
}

class Memento{
    private String state;

    public Memento(String state){
        this.state = state;
    }
    public String getState() {
        return state;
    }
}
class Caretaker{
    private List<Memento> mementoList = new ArrayList<>();

    public void addMemento(Memento memento){
        mementoList.add(memento);
    }

    public Memento getMemento(int index){
        if (index >= 1 && index < mementoList.size()){return mementoList.get(index-1);}
        return null;
    }
    public void showMemento(){
        int cnt = 1;
        for(Memento memento : mementoList){
            System.out.println("第" + cnt + "次备份,状态为" + memento.getState());
            cnt++;
        }
    }
}

7、观察者模式(Observer)

意图

定义对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖与他的对象都得到通知并被自动更新

适用性

1.当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两者封装在独立的对象中以使它们可以各自独立改变和复用

2.当对一个对象改变需要同时改变其他对象,而不知道具体有多少对象有待改变时

3.当一个对象必须通知其他对象,而它又不能假定其他对象是谁,即不希望这些对象是紧耦合的

实现代码

package com.yhw.observerPattern;

import java.util.*;
//观察者模式
public class ObserverPattern {
    public static void main(String[] args) {
        Subject subjectA = new ConcreteSubject("目标A");

        Observer observerB = new ConcreteObserver("张三" , subjectA);
        Observer observerC = new ConcreteObserver("李四" , subjectA);
        Observer observerD = new ConcreteObserver("王五" , subjectA);

        System.out.println(subjectA.getState());
        System.out.println("=======================");
        subjectA.setState("更新了");
        System.out.println("=======================");
        subjectA.Detach(observerD);
        subjectA.setState("停更了");
    }
}
interface Subject{
    public void Attach(Observer observer);//添加观察者
    public void Detach(Observer observer);//删除观察者
    public void Notify();//状态改变后通知所有观察者
    public String getState();
    public void setState(String state);
}//目标接口

class ConcreteSubject implements Subject{
    private List<Observer> observerList;
    private String state;
    private String name;

    public ConcreteSubject(String name){
         = name;
        state = "未更新";
        observerList = new ArrayList<Observer>();
    }

    public String getState(){
        return state;
    }

    public void setState(String state){
        this.state = state;
        System.out.println(name+"的状态发生改变,变化后的状态为:"+state);
        Notify();
    }

    @Override
    public void Attach(Observer observer) {
        observerList.add(observer);
    }

    @Override
    public void Detach(Observer observer) {
        observerList.remove(observer);
    }

    @Override
    public void Notify() {
        for(Observer observer : observerList){
            observer.update();
        }
    }
}

interface Observer{
    public void update();//收到通知,更新观察者的状态
}//观察者接口

class ConcreteObserver implements Observer{
    private String name;
    private Subject subject;
    private String state;

    public ConcreteObserver(String name,Subject subject){
         = name;
        this.subject = subject;

        subject.Attach(this);
        state = subject.getState();
    }
    public String getState(){
        return state;
    }

    @Override
    public void update() {
        System.out.println(name+"收到通知");
        state = subject.getState();//当前观察者的状态和改变了状态之后的目标状态保持一致
        System.out.println(name + "改变后的状态为:" + state);
    }
}

8、状态(State)

意图

允许一个对象在其内部状态改变时改变他的行为。对象看起来似乎修改了它的类。

适用性

1.一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为

2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态常用一个或多个枚举常量表示

实现代码

package com.yhw.statePattern;
//状态模式
public class StatePattern {
    public static void main(String[] args) {
        Context context = new Context();

        System.out.println(context.getState());//count = 3  stateA

        context.Request();//count = 2
        context.Request();//count = 1
        context.Request();//count = 0

        System.out.println(context.getState());//stateB

        context.Request();//count = 5

        System.out.println(context.getState());//stateA
    }
}
class Context{
    private int count;
    private State state;

    public Context(){
        count = 3;
        state = new StateA();
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public State getState() {
        return state;
    }

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

    public void Request(){//购买饮料
        state.Handle(this);
    }
}

interface State{
    public void Handle(Context context);
}

class StateA implements State{//有货

    @Override
    public void Handle(Context context) {
        int count = context.getCount();

        if (count >= 1){
            System.out.println("购买成功");
            context.setCount(count - 1);

            if (context.getCount() == 0){
                context.setState(new StateB());
            }
        }else System.out.println("购买失败!");

    }
}
class StateB implements State{//无货

    @Override
    public void Handle(Context context) {
        int count = context.getCount();

        if (count == 0){
            System.out.println("购买失败!等待补货");

            context.setCount(5);
            System.out.println("补货成功,请重新购买");
            context.setState(new StateA());
        }
    }
}

9、策略(Strategy)

意图

定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。此算法模式使得算法可以独立于使用它们的客户而变化。

适用性

1.许多相关的类仅仅是行为有异。”策略“提供一种用多个行为中的一个行为来配置一个类的方法

2.需要使用一个算法的不同变体

3.算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的,与算法相关的数据结构

4.一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,将相关的条件分支移入它们各自的Strategy类中,以代替这些条件语句。

实现代码

package com.yhw.strategyPattern;
//策略模式
public class StrategyPattern {//两数运算方法

    public static void main(String[] args) {
        Strategy add = new AddStrategy();
        Strategy subtraction = new SubtractionStrategy();
        Strategy multiply = new MultiplyStrategy();

        OperationContext context = new OperationContext(add);
        context.Operation(2022,115);

        context = new OperationContext(subtraction);
        context.Operation(2022,115);

        context = new OperationContext(multiply);
        context.Operation(2022,115);
    }
}

class OperationContext{
    private Strategy strategy;

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

    public void Operation(int a , int b){
        strategy.TwoNumberOperation(a,b);
    }
}
interface Strategy{
    public void TwoNumberOperation(int a , int b );
}

class AddStrategy implements Strategy{
    @Override
    public void TwoNumberOperation(int a, int b) {
        System.out.println(a + b);
    }//加法运算
}
class SubtractionStrategy implements Strategy{
    @Override
    public void TwoNumberOperation(int a, int b) {
        System.out.println(a - b);
    }//减法运算
}
class MultiplyStrategy implements Strategy{
    @Override
    public void TwoNumberOperation(int a, int b) {
        System.out.println(a * b);
    }//乘法运算
}

10、(类)模板方法(Template Method)

意图

定义一个操作中的算法骨架,而将一些步骤延迟到子类中。Template Method 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

适用性

1.一次性实现一个算法的不变部分,并将可变的行为留给子类来实现

2.各子类中公共的行为应被提取出来并集中到一个公共父类中,以避免代码重复

3.控制子类扩展,模板方法特定点调用”hook”操作(默认的行为,子类可以在必要时进行重定义扩展),这就只允许在这些点进行扩展。

实现代码

package com.yhw.templateMethodPattern;
//模板方法模式
public class TemplateMethodPattern {
    public static void main(String[] args) {
        Person student = new Student();
        Person teacher = new Teacher();

        student.TemplateMethod();
        System.out.println("====================");
        teacher.TemplateMethod();

    }
}

abstract class Person{
    public void TemplateMethod(){
        System.out.println("上课 去教室");
        PrimitiveOperation1();
        System.out.println("下课 离开教室");
        PrimitiveOperation2();
    }
    public abstract void PrimitiveOperation1();//原语操作1:上课过程 学生 听课  老师 讲课
    public abstract void PrimitiveOperation2();//原语操作2:作业 学生 写作业  老师 改作业
}

class Student extends Person{

    @Override
    public void PrimitiveOperation1() {
        System.out.println("学生:听课 学习 做笔记");
    }

    @Override
    public void PrimitiveOperation2() {
        System.out.println("学生:写作业 提交作业");
    }
}

class Teacher extends Person{

    @Override
    public void PrimitiveOperation1() {
        System.out.println("老师:上课 解答问题 布置作业");
    }

    @Override
    public void PrimitiveOperation2() {
        System.out.println("老师:改作业 打分数");
    }
}

11、访问者(Visitor)

意图

表示一个作用于某对象结构中的各元素操作。它允许在不改变各元素的类的前提下定义作用于这些元素的新操作。

适用性

1.一个对象结构包含很多类对象,它们有不同的接口,而用户想对这些对象实施一些依赖于其具体类的操作

2.需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而又想要避免这些操作“污染”这些对象的类。

3.定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。

实现代码

1.访问者简单实现

package com.yhw.visitorPattern;
import java.util.*;
//访问者模式
public class VisitorPattern {
    public static void main(String[] args) {
        PersonStructure structure = new PersonStructure();

        Visitor visitor1 = new Visitor1();
        Visitor visitor2 = new Visitor2();

        System.out.println("访问者1的访问记录:");
        structure.Accept(visitor1);
        System.out.println("=================");
        System.out.println("访问者2的访问记录:");
        structure.Accept(visitor2);
    }
}

interface Visitor{
    public void visitStudent(Student student);
    public void visitTeacher(Teacher teacher);//方法的重载(方法名相同,参数的类型不同)
}

class Visitor1 implements Visitor{
    @Override
    public void visitStudent(Student student) {
        System.out.println("访问者1访问学生:" + );
    }

    @Override
    public void visitTeacher(Teacher teacher) {
        System.out.println("访问者1访问老师:" + );
    }
}

class Visitor2 implements Visitor{
    @Override
    public void visitStudent(Student student) {
        System.out.println("访问者2访问学生:" + );
    }

    @Override
    public void visitTeacher(Teacher teacher) {
        System.out.println("访问者2访问老师:" + );
    }
}

class PersonStructure{//对象结构(可以存很多很多的Person)
    private List<Person> personList = new ArrayList<Person>();

    public PersonStructure(){
        personList.add(new Student("张三"));
        personList.add(new Student("李四"));
        personList.add(new Student("王五"));

        personList.add(new Teacher("李老师"));
        personList.add(new Teacher("刘老师"));
        personList.add(new Teacher("王老师"));
    }

    public void Accept(Visitor visitor){//高层接口,允许访问者访问它的元素
        for(Person person : personList){
            person.Accept(visitor);
        }
    }
}

abstract class Person{
    public String name;

    public abstract void Accept(Visitor visitor);//接受访问的方法
}

class Student extends Person{

    public Student(String name){
         = name;
    }

    @Override
    public void Accept(Visitor visitor) {
        visitor.visitStudent(this);
    }
}

class Teacher extends Person{

    public Teacher(String name){
         = name;
    }

    @Override
    public void Accept(Visitor visitor) {
        visitor.visitTeacher(this);
    }
}

2.访问者具体操作实现

package com.yhw.visitorPattern1;
import java.util.*;
//访问者模式(实现访问者的具体的操作)
public class VisitorPattern1 {
    public static void main(String[] args) {
        PersonStructure structure = new PersonStructure();

        Visitor1 visitor1 = new Visitor1();
        Visitor2 visitor2 = new Visitor2();

        System.out.println("访问者1的访问记录:");
        structure.Accept(visitor1);
        System.out.println("学生年龄的总和:" + visitor1.getStudentAgeSum() + " 老师年龄的总和:" + visitor1.getTeacherAgeSum());
        System.out.println("=================");
        System.out.println("访问者2的访问记录:");
        structure.Accept(visitor2);
        System.out.println("学生成绩的最大值:" + visitor2.getMaxScore() + " 老师工龄的最大值:" + visitor2.getMaxWorkYear());

    }
}

interface Visitor{
    public void visitStudent(Student student);
    public void visitTeacher(Teacher teacher);//方法的重载(方法名相同,参数的类型不同)
}

class Visitor1 implements Visitor{//访问者1:分别统计学生和老师的年龄总和
    private int studentAgeSum = 0;
    private int teacherAgeSum = 0;

    @Override
    public void visitStudent(Student student) {
        System.out.println("访问者1访问学生:" + student.getName() + "年龄"+ student.getAge());
        studentAgeSum += student.getAge();
    }

    @Override
    public void visitTeacher(Teacher teacher) {
        System.out.println("访问者1访问老师:" + teacher.getName() + "年龄" + teacher.getAge());
        teacherAgeSum += teacher.getAge();
    }

    public int getStudentAgeSum() {
        return studentAgeSum;
    }

    public int getTeacherAgeSum() {
        return teacherAgeSum;
    }
}

class Visitor2 implements Visitor{//
    private int maxScore = -1;
    private int maxWorkYear = -1;

    @Override
    public void visitStudent(Student student) {//访问者2:分别求出学生的最高成绩,以及老师的最高工龄
        System.out.println("访问者2访问学生:" + student.getName() + "成绩" + student.getScore());
        maxScore = Math.max(maxScore , student.getScore());
    }

    @Override
    public void visitTeacher(Teacher teacher) {
        System.out.println("访问者2访问老师:" + teacher.getName() + "工龄" + teacher.getWorkYear());
        maxWorkYear = Math.max(maxWorkYear , teacher.getWorkYear());
    }

    public int getMaxScore() {
        return maxScore;
    }

    public int getMaxWorkYear() {
        return maxWorkYear;
    }
}

class PersonStructure{//对象结构(可以存很多很多的Person)
    private List<Person> personList = new ArrayList<Person>();

    public PersonStructure(){
        personList.add(new Student("张三",20,70));
        personList.add(new Student("李四",21,80));
        personList.add(new Student("王五",22,90));

        personList.add(new Teacher("李老师",24,1));
        personList.add(new Teacher("刘老师",25,2));
        personList.add(new Teacher("王老师",26,3));
    }

    public void Accept(Visitor visitor){//高层接口,允许访问者访问它的元素
        for(Person person : personList){
            person.Accept(visitor);
        }
    }
}

abstract class Person{
    private String name;
    private int age;

    public Person(String name , int age){
         = name;
        this.age = age;
    }

    public abstract void Accept(Visitor visitor);//接受访问的方法

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

class Student extends Person{
    private int score;//成绩

  public Student(String name , int age ,int score){
      super(name, age);
      this.score = score;
  }
    @Override
    public void Accept(Visitor visitor) {
        visitor.visitStudent(this);
    }

    public int getScore() {
        return score;
    }
}

class Teacher extends Person{
    private int workYear;//工龄

    public Teacher(String name , int age , int workYear){
        super(name, age);
        this.workYear = workYear;
    }
    @Override
    public void Accept(Visitor visitor) {
        visitor.visitTeacher(this);
    }

    public int getWorkYear() {
        return workYear;
    }
}