设计模式JAVA

1 创建型

如何合理的创建对象?

1.1 单例模式

字面意思就是只能创建一个对象实例时使用。

例如,Windows中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。

特点:全局就这一个对象时

懒汉式的实现方式如下:

/*** 懒汉单例模式*/
public class SingleLazyDemo {//避免在外部被实例化private SingleLazyDemo() {}private static volatile SingleLazyDemo instance = null;//实例化public static synchronized SingleLazyDemo getInstance(){if(instance == null){instance = new SingleLazyDemo();}return  instance;}}

测试效果如下: 

 

 饿汉式实现方式如下:

public class SingleHungryDemo {//避免在外部被实例化private SingleHungryDemo() {}private static final SingleHungryDemo instance ;//一旦加载就创建一个单例static {instance = new SingleHungryDemo();}//实例化public static synchronized SingleHungryDemo getInstance(){return instance;}
}

饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。

1.2 原型模式

特点:应用于克隆型对象创建,拷贝原型创建新的对象

原型模式的克隆分为浅克隆和深克隆,Java中的Object类提供了浅克隆的clone()方法,具体原型类只要实现Cloneable接口就可实现对象的浅克隆。

浅克隆的实现方式如下:

import lombok.Data;@Data
public class PrototypeShallowDemo implements Cloneable{private String name;private String describe;public PrototypeShallowDemo(String name,String describe){this.name = name;this.describe = describe;}@Overridepublic String toString(){return "my name is " + name + ", my info is " + describe;}protected Object clone() throws CloneNotSupportedException{return super.clone();}}

测试效果如下:

浅拷贝的特点:

  • 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象;
  • 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,即克隆一份地址。 

深拷贝可以使用对象序列化的方式实现:

@Data
public class PrototypeDeepDemo implements Cloneable, Serializable {private String name;private PrototypeShallowDemo prototypeShallowDemo;@Overrideprotected Object clone() throws CloneNotSupportedException {Object object = super.clone();PrototypeDeepDemo prototypeDeepDemo = (PrototypeDeepDemo) object;prototypeDeepDemo.prototypeShallowDemo = (PrototypeShallowDemo) prototypeShallowDemo.clone();return object;}
}

1.3 工厂方法模式

特点:创建于使用分离,将创建的对象作为“产品”,把创建产品的对象称为“工厂”。

满足“开闭原则”的前提下,客户随意增删或改变对软件相关对象的使用。

首先实现要生产的产品:

//定一个产品类
public interface Product {public String Show();
}//具体产品1
public class ProductCoffee implements Product{@Overridepublic String Show() {return "this is coffee";}
}//具体产品2
public class ProductPhone implements Product{@Overridepublic String Show() {return "this is phone";}
}

然后实现生产工厂:

//定义一个抽象工厂,使用接口interface或者抽象abstract
public interface AbstractFactory {public Product CreateProduct();
}//具体的生产工厂1
public class FactoryCoffee implements AbstractFactory{@Overridepublic Product CreateProduct() {return new ProductCoffee();}
}//具体的生产工厂2
public class FactoryPhone implements AbstractFactory{@Overridepublic Product CreateProduct() {return new ProductPhone();}
}

测试实例,调用不同的工厂生产产品:

    @GetMapping("/demo4")public String demo4() {FactoryCoffee factoryCoffee = new FactoryCoffee();Product product = factoryCoffee.CreateProduct();FactoryPhone factoryPhone = new FactoryPhone();return product.Show() + "______" + factoryPhone.CreateProduct().Show();}

 1.4 抽象工厂模式

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

使用抽象工厂模式一般要满足以下条件。

① 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。

② 系统一次只可能消费其中某一族产品,即同族的产品一起使用。

在抽象工厂模式包含如下几个角色:

  • AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。
  • ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。
  • AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法
  • ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。

1)创建抽象产品和具体产品

//抽象产品1
public abstract class Animal {public abstract void getName();public abstract void addFood();public abstract void getColor();
}//具体动物1
public class Horse extends Animal{@Overridepublic void getName() {System.out.println("this name is horse");}@Overridepublic void addFood() {System.out.println("添加食物");}@Overridepublic void getColor() {System.out.println("白色");}
}//具体动物2
public class Cattle extends Animal{@Overridepublic void getName() {System.out.println("this name is cattle");}@Overridepublic void addFood() {System.out.println("添加食物");}@Overridepublic void getColor() {System.out.println("黑色");}
}//抽象产品2
public abstract class Plant {public abstract void getName();public abstract void addWater();
}//具体植物1
public class Fruit extends Plant{@Overridepublic void getName() {System.out.println("这是水果");}@Overridepublic void addWater() {System.out.println("浇水");}
}//具体植物2
public class Vegetable extends Plant{@Overridepublic void getName() {System.out.println("这是蔬菜");}@Overridepublic void addWater() {System.out.println("浇水");}
}

2)抽象工厂

public interface Farm {public Plant createPlant();public Animal createAnimal();
}

3)具体工厂

//具体工厂1
public class HongXingFarm implements Farm{@Overridepublic Plant createPlant() {System.out.println("蔬菜产生");return new Vegetable();}@Overridepublic Animal createAnimal() {System.out.println("牛产生");return new Cattle();}
}//具体工厂2
public class MingLeFarm implements Farm{@Overridepublic Plant createPlant() {System.out.println("水果产生");return new Fruit();}@Overridepublic Animal createAnimal() {System.out.println("马产生");return new Horse();}
}

 4)测试

    @GetMapping("/demo5")public void demo5(){Farm farm ;Animal animal;Plant plant;farm = new HongXingFarm();animal = farm.createAnimal();plant = farm.createPlant();animal.getName();animal.addFood();plant.getName();plant.addWater();}

1.5 建造者模式

背景:在软件开发过程中有时需要创建一个复杂的对象,这个复杂对象通常由多个子部件按一定的步骤组合而成。例如,计算机是由CPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件组装而成的。

它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

建造者模式的主要角色如下:

  • 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个组成部件。
  • 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法getResult()。
  • 具体建造者(Concrete Builder):实现Builder接口,完成复杂产品的各个部件的具体创建方法。
  • 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

1)设计产品构成

public class Product  {private  String partA;private  String partB;private  String partC;public void setPartA(String partA) {this.partA = partA;}public void setPartB(String partB) {this.partB = partB;}public void setPartC(String partC) {this.partC = partC;}public void show(){System.out.println(partA + partB + partC);}
}

2)建造者,负责进行产品的组装

public abstract class Builder {//创建产品对象protected  Product product=new Product();public  abstract void buildPartA();public  abstract void buildPartB();public  abstract void buildPartC();//返回产品对象public  Product getResult() {return  product;}
}

3)具体构造者,实现具体的构建细节

public class HongXIngBuilder extends Builder{@Overridepublic void buildPartA() {product.setPartA("建造PartA");}@Overridepublic void buildPartB() {product.setPartB("建造PartB");}@Overridepublic void buildPartC() {product.setPartC("建造PartC");}
}

4)指挥者,选择具体构建者进行构建

public class Director {private  Builder builder;public  Director(Builder builder) {this.builder=builder;}//产品构建与组装方法public Product construct() {builder.buildPartA();builder.buildPartB();builder.buildPartC();return builder.getResult();}
}

5)使用

    @GetMapping("/demo6")public void demo6(){//选择HongXIngBuilderBuilder builder1 = new HongXIngBuilder();Director director1 = new Director(builder1);Product product1 = director1.construct();product1.show();}

2 结构型

结构型模式字面意思就是设计程序结构的。

2.1 代理模式

代理就类似于中介,某些情况下不能或者不想直接访问另一个对象,这时需要找一个中介帮忙完成某项任务,这个中介就是代理对象。

代理模式的主要角色如下:

  • 抽象主题(Subject)类:通过接口或抽象类声明真实主题和代理对象实现的业务方法。
  • 真实主题(Real Subject)类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
  • 代理(Proxy)类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。

1)抽象主题

public interface Subject {void Request();void GetInfo();
}

2)真实主题

public class RealSubject implements Subject{@Overridepublic void Request() {System.out.println("【*】开始访问 ");}@Overridepublic void GetInfo() {System.out.println("【info】信息展示 "  + new Date());}
}

3)代理

public class Proxy implements Subject{private RealSubject realSubject;@Overridepublic void Request() {if(realSubject == null){realSubject = new RealSubject();}preRequest();realSubject.Request();postRequest();}@Overridepublic void GetInfo() {if(realSubject == null){realSubject = new RealSubject();}realSubject.GetInfo();}

4)使用

    @GetMapping("/demo7")public void demo7(){Proxy proxy = new Proxy();proxy.GetInfo();proxy.Request();}

 2.2 适配器模式

开发中两个对象因接口不兼容而不能在一起工作的实例,这时需要第三者进行适配。适配器模式就是将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

适配器模式包含以下主要角色:

  • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
  • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
  • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

1)目标接口

public interface Target {void Request();
}

2)适配目标类

public class Adapter {public void specificRequest(){System.out.println("适配具体请求");}}

 3)适配器

public class TargetAdapter extends Adapter implements Target {@Overridepublic void Request() {specificRequest();}
}

4)使用

    @GetMapping("/demo8")public void demo8(){Target target = new TargetAdapter();target.Request();}

2.3 桥接模式

将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

桥接(Bridge)模式包含以下主要角色:

  • 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化(Implementor)角色的引用。Abstraction 充当桥接类。
  • 扩展抽象化(Refined Abstraction)角色:是抽象化(Abstraction)角色的子类,实现父类中的业务方法,并通过组合关系调用实现化(Implementor)角色中的业务方法。
  • 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化(Refined Abstraction)角色调用。
  • 具体实现化(Concrete Implementor)角色:给出实现化(Implementor)角色接口的具体实现。

比如4种类型画笔,3种颜色,实现一个画板:

实现方式1: 四种画笔,每种画笔创建三种颜色,共4 *3 = 12 个类

实现方式2:如下,四个形状具体实现类,三个颜色具体实现类,然后定义双继承,也是12个类

实现方式3:如下,用个“桥”去拼接形状和颜色,只有一座“桥”所以类的数量就看上面的4+3=7 

//实现化角色
public interface Impl {public void ImplInfo();
}//具体实现化角色
public class TypeOneImpl implements Impl{@Overridepublic void ImplInfo() {System.out.println("具体实现1");}
}//抽象化角色
public abstract class Abstr {protected Impl impl;protected Abstr(Impl impl){this.impl = impl;}public abstract void Operation();
}//扩展抽象化角色
public class AbstrOne extends Abstr{public AbstrOne(Impl impl) {super(impl);}@Overridepublic void Operation() {System.out.println("扩展抽象化访问");impl.ImplInfo();}}//使用@GetMapping("/demo9")public void demo9(){Impl impl = new TypeOneImpl();Abstr abstr = new AbstrOne(impl);abstr.Operation();}

2.4 装饰模式

在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。

装饰模式主要包含以下角色:

  • 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
  • 具体构件(Concrete Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
  • 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  • 具体装饰(Concrete Decorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

1)抽象构件角色

public interface Shape {void draw();
}

2)具体构件角色,未被修饰的原本的内容

public class Rectangle implements Shape{@Overridepublic void draw() {System.out.println("Shape: Rectangle");}
}public class Circle implements Shape{@Overridepublic void draw() {System.out.println("Shape: Circle");}
}

3)抽象修饰角色

public abstract class ShapeDecorator implements Shape{protected Shape shape;public ShapeDecorator(Shape shape){this.shape = shape;}public void draw(){shape.draw();}
}

4)具体修饰角色,添加修饰类型——颜色修饰

public class RedShapeDecorator extends ShapeDecorator{public RedShapeDecorator(Shape shape) {super(shape);}@Overridepublic void draw(){shape.draw();setRedBorder(shape);}private void setRedBorder(Shape shape){System.out.println("Border Color: Red");}}

5)使用

    @GetMapping("/demo10")public void demo10(){Shape shapeCircle = new Circle();ShapeDecorator redCircle = new RedShapeDecorator(new Circle());ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());shapeCircle.draw();System.out.println("-----");redCircle.draw();redRectangle.draw();}

2.5 外观模式

当一个系统的功能越来越强,子系统会越来越多,客户对系统的访问也变得越来越复杂。这时如果系统内部发生改变,客户端也要跟着改变,这违背了“开闭原则”,也违背了“迪米特法则”,所以有必要为多个子系统提供一个统一的接口,从而降低系统的耦合度。

外观模式包含以下主要角色:

  • 外观(Facade)角色:为多个子系统对外提供一个共同的接口。
  • 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
  • 客户(Client)角色:通过一个外观角色访问各个子系统的功能。

1)外观角色

public interface Shape {void draw();
}

2)子系统

public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Rectangle::draw()");}
}public class Square implements Shape {@Overridepublic void draw() {System.out.println("Square::draw()");}
}

3)客户角色

public class ShapeMaker {private Shape circle;private Shape rectangle;public ShapeMaker() {circle = new Circle();rectangle = new Rectangle();square = new Square();}public void drawCircle(){circle.draw();}public void drawRectangle(){rectangle.draw();}}

4)使用

      ShapeMaker shapeMaker = new ShapeMaker();shapeMaker.drawCircle();shapeMaker.drawRectangle();

2.6 享元模式

在面向对象程序设计过程中,有时会面临要创建大量相同或相似对象实例的问题。

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

享元模式的主要角色有如下:

  • 抽象享元角色(Flyweight):是所有的具体享元类的基类,为具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
  • 具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
  • 非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
  • 享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检查系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

1)非享元

public class UnSharedFlyweight {private String info;public UnSharedFlyweight(String info){this.info = info;}public String getInfo(){return info;}public void setInfo(String info){this.info = info;}
}

2)抽象享元

public interface AbstractFlyweight {void operation(UnSharedFlyweight unSharedFlyweight);
}

3)具体享元

public class ConcreteFlyweight implements AbstractFlyweight{private String key;public ConcreteFlyweight(String key){this.key = key;System.out.println("具体享元" + key + "被创建!");}@Overridepublic void operation(UnSharedFlyweight unSharedFlyweight) {System.out.print("具体享元" + key + "被调用, ");System.out.println("非享元信息是 " + unSharedFlyweight.getInfo());}
}

4)享元工厂

public class FlyweightFactory {private HashMap<String,AbstractFlyweight> flyweights = new HashMap<String,AbstractFlyweight>();public AbstractFlyweight getFlyweight(String key){AbstractFlyweight flyweight = flyweights.get(key);if(flyweight != null){System.out.println("具体享元" + key + "已经存在,获取成功!");}else{flyweight = new ConcreteFlyweight(key);flyweights.put(key,flyweight);}return flyweight;}}

5)使用

    @GetMapping("/demo11")public void demo11(){FlyweightFactory factory = new FlyweightFactory();AbstractFlyweight flyweight1 = factory.getFlyweight("a");AbstractFlyweight flyweight2 = factory.getFlyweight("a");AbstractFlyweight flyweight3 = factory.getFlyweight("b");AbstractFlyweight flyweight4 = factory.getFlyweight("b");AbstractFlyweight flyweight5 = factory.getFlyweight("b");flyweight1.operation(new UnSharedFlyweight("第一次调用a"));flyweight2.operation(new UnSharedFlyweight("第二次调用a"));flyweight3.operation(new UnSharedFlyweight("第一次调用b"));flyweight4.operation(new UnSharedFlyweight("第二次调用b"));flyweight5.operation(new UnSharedFlyweight("第三次调用b"));}

实例应用:棋子(ChessPieces)类是抽象享元角色,它包含了一个落子的DownPieces(Graphics g,Point pt)方法;白子(WhitePieces)和黑子(BlackPieces)类是具体享元角色,它实现了落子方法;Point是非享元角色,它指定了落子的位置;WeiqiFactory是享元工厂角色,它通过ArrayList来管理棋子,并且提供了获取白子或者黑子的getChessPieces(String type)方法。 

2.7 组合模式

有时又叫作部分-整体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。

透明组合模式

//抽象构件
interface Component {public void add(Component c);public void remove(Component c);public Component getChild(int i);public void operation();
}//树叶构件
class Leaf implements Component {private String name;public Leaf(String name) {this.name = name;}public void add(Component c) {}public void remove(Component c) {}public Component getChild(int i) {return null;}public void operation() {System.out.println("树叶" + name + ":被访问!");}
}//树枝构件
class Composite implements Component {private ArrayList<Component> children = new ArrayList<Component>();public void add(Component c) {children.add(c);}public void remove(Component c) {children.remove(c);}public Component getChild(int i) {return children.get(i);}public void operation() {for (Object obj : children) {((Component) obj).operation();}}
}//使用Component c0 = new Composite();Component c1 = new Composite();Component leaf1 = new Leaf("1");Component leaf2 = new Leaf("2");Component leaf3 = new Leaf("3");c0.add(leaf1);c0.add(c1);c1.add(leaf2);c1.add(leaf3);c0.operation();

3 行为型模式

3.1 模版方法模式

场景:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关。又例如例如,简历模板、论文模板、Word中模板文件等。

模版方法模式特点如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。

模板方法模式包含以下主要角色:

(1)抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下

        ① 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。

        ② 基本方法:是整个算法中的一个步骤,包含以下几种类型。

(2)具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。

//抽象类
public abstract class StencilAbstract {public void TemplateMethod() {    //模版方法SpecificMethod();abstractMethod1();abstractMethod2();}public void SpecificMethod(){    //具体方法System.out.println("抽象类中的具体方法被调用");}public abstract void abstractMethod1();public abstract void abstractMethod2();
}//具体子类
public class ConcreteStencil extends StencilAbstract {@Overridepublic void abstractMethod1() {System.out.println("抽象方法1的实现调用");}@Overridepublic void abstractMethod2() {System.out.println("抽象方法2的实现调用");}
}//调用@GetMapping("/demo12")public void demo12(){StencilAbstract sa = new ConcreteStencil();sa.TemplateMethod();}

3.2 策略模式

当实现某一个功能存在多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。

策略模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。

策略模式的主要角色如下:

  • 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
  • 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

1)抽象策略类

public interface AbstractStrategy {public void strategyMethod();
}

2)具体策略类

//具体实现方法2
public class ConcreteStrategyA implements AbstractStrategy{@Overridepublic void strategyMethod() {System.out.println("具体策略A的策略方法被访问!");}
}//具体实现方法1
public class ConcreteStrategyB implements AbstractStrategy{@Overridepublic void strategyMethod() {System.out.println("具体策略B的策略方法被访问!");}
}

3)环境类

public class EnvironmentContext {private AbstractStrategy strategy;public AbstractStrategy getStrategy(){return strategy;}public void setStrategy(AbstractStrategy getStrategy){this.strategy = strategy;}public void strategyMethod(){strategy.strategyMethod();}
}

4)调用

    @GetMapping("/demo13")public void demo13(){EnvironmentContext context = new EnvironmentContext();AbstractStrategy strategy = new ConcreteStrategyA();context.setStrategy(strategy);context.strategyMethod();System.out.println("_______________");strategy = new ConcreteStrategyB();context.setStrategy(strategy);context.strategyMethod();}

3.3 命令模式

背景:在软件开发系统中,常常出现“方法的请求者”与“方法的实现者”之间存在紧密的耦合关系。

命令模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理。

命令模式包含以下主要角色:

  • 抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法execute()。
  • 具体命令角色(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
  • 实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
  • 调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。

1)抽象命令类

//抽象命令
public interface Command {public abstract void execute();
}

2)具体命令类

public class ConcreteCommand implements Command{private Receiver receiver;public ConcreteCommand(){receiver = new Receiver();}@Overridepublic void execute() {receiver.action();}
}

3)调用者,发起请求的地方

public class Invoker {private Command command;public Invoker (Command command){this.command = command;}public void setCommand(Command command){this.command = command;}public void call(){System.out.println("调用者治性命令!");command.execute();}
}

4)接收者,真正实现业务的地方

public class Receiver {public void action(){System.out.println("接受者的action()方法被调用");}
}

5)调用实现

    @GetMapping("/demo14")public void demo14(){Command cmd = new ConcreteCommand();Invoker invoker = new Invoker(cmd);invoker.call();}

3.4 职责链模式

背景:一个请求有多个对象可以处理,但每个对象的处理条件或权限不同。例如Struts2的拦截器、JSP和Servlet的Filter。

职责链模式:为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

职责链模式主要包含以下角色:

  • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
  • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
  • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

1)抽象处理者

public abstract class RCAbstractHandler {private RCAbstractHandler next;public void setNext(RCAbstractHandler next){this.next = next;}public RCAbstractHandler getNext(){return next;}//处理请求的方法public abstract void handleRequest(String request);}

2)具体处理者

//具体处理者1
public class ConcreteHandle1 extends RCAbstractHandler{@Overridepublic void handleRequest(String request) {if(request.contains("a")){System.out.println("ConcreteHandle1 开始处理");}else {if(getNext() != null){getNext().handleRequest(request);}else{System.out.println("无处理");}}}}//具体处理者2
public class ConcreteHandle2 extends RCAbstractHandler{@Overridepublic void handleRequest(String request) {if(request.contains("b")){System.out.println("ConcreteHandle2 开始处理");}else {if(getNext() != null){getNext().handleRequest(request);}else{System.out.println("无处理");}}}
}

3)调用

    @GetMapping("/demo15")public void demo15(@RequestParam("content") String content){RCAbstractHandler handler1 = new ConcreteHandle1();RCAbstractHandler handler2 = new ConcreteHandle2();handler1.setNext(handler2);handler1.handleRequest(content);}

 3.5 状态模式

背景:应用程序中的有些对象可能会根据不同的情况做出不同的行为,我们把这种对象称为有状态的对象。

状态模式:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

状态模式包含以下主要角色:

  • 环境(Context)角色:也称为上下文,它定义了客户感兴趣的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
  • 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
  • 具体状态(Concrete State)角色:实现抽象状态所对应的行为。

1)环境角色

public class StateContext {private State state;public StateContext(){this.state = new ConcreteStateA();}public void setState(State state){this.state = state;}public State getState(){return state;}public void Handle(State state){state.Handle(this,state);}
}

2)抽象状态

public abstract class State {public abstract void Handle(StateContext context,State state);
}

3)具体状态

//具体算法A
public class ConcreteStateA extends State{@Overridepublic void Handle(StateContext context,State state) {System.out.println("this is A");context.setState(state);}
}//具体算法B
public class ConcreteStateB extends State{@Overridepublic void Handle(StateContext context,State state) {System.out.println("this is B");context.setState(state);}
}

4)调用

    @GetMapping("/demo16")public void demo16(){StateContext context = new StateContext();context.Handle(new ConcreteStateA());context.Handle(new ConcreteStateA());context.Handle(new ConcreteStateB());}

3.6 观察者模式

背景:在现实世界中,许多对象并不是独立存在的,其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变

观察者(订阅者)模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式的主要角色如下:

  • 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
  • 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
  • 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
  • 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。

1)抽象主题角色

public abstract class ObserverSubject {protected List<Observer> observers=new ArrayList<Observer>();//增加观察者方法public void add(Observer observer){observers.add(observer);}//删除观察者方法public void remove(Observer observer){observers.remove(observer);}public abstract void notifyObserver(String info); //通知观察者方法
}

2)具体主题

public class ObConcreteSubject extends ObserverSubject {@Overridepublic void notifyObserver(String info) {System.out.println("具体目标发生改变...");System.out.println("--------------");for(Object obs:observers){((Observer)obs).response(info);}}
}

3)抽象观察者

public interface Observer {void response(String info);
}

4)具体观察者角色

//具体观察者1
public class ObConcreteObserver1 implements Observer{@Overridepublic void response(String info) {System.out.println("具体观察者1作出反应:" + info);}
}//具体观察者2
public class ObConcreteObserver1 implements Observer{@Overridepublic void response(String info) {System.out.println("具体观察者1作出反应:" + info);}
}

5)调用

    @GetMapping("/demo17")public void demo17(){ObserverSubject subject = new ObConcreteSubject();Observer observer1 = new ObConcreteObserver1();Observer observer2 = new ObConcreteObserver2();subject.add(observer1);subject.add(observer2);subject.notifyObserver("降价了!");}

 3.7 中介模式

背景:在现实生活中,常常会出现好多对象之间存在复杂的交互关系,这种交互关系常常是“网状结构”,它要求每个对象都必须知道它需要交互的对象。

中介模式(调停模式):定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。

中介者模式包含以下主要角色:

  • 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
  • 具体中介者(Concrete Mediator)角色:实现中介者接口,定义一个List来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
  • 抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
  • 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

1)中介者

//抽象中介者
public abstract class AbstractMediator {public abstract void register(AbstractCollege college);public abstract void replay(AbstractCollege cl);
}//具体中介者
public class ConcreteMediator extends AbstractMediator{private List<AbstractCollege> colleges = new ArrayList<>();@Overridepublic void register(AbstractCollege college) {if(!colleges.contains(college)){colleges.add(college);college.setMediator(this);}}@Overridepublic void replay(AbstractCollege cl) {for(AbstractCollege college : colleges){if(!college.equals(cl)){college.receive();}}}
}

2)同事类

//抽象
public abstract class AbstractCollege {protected AbstractMediator mediator;public void setMediator(AbstractMediator mediator){this.mediator = mediator;}public abstract void receive();public abstract void send();
}//具体1
public class ConcreteCollege1 extends AbstractCollege{@Overridepublic void receive() {System.out.println("college1 收到请求 ");}@Overridepublic void send() {System.out.println("college1 发出请求 ");mediator.replay(this);//转发}
}//具体2
public class ConcreteCollege2 extends AbstractCollege {@Overridepublic void receive() {System.out.println("college2 收到请求 ");}@Overridepublic void send() {System.out.println("college2 发出请求 ");mediator.replay(this);}
}

3)调用

    @GetMapping("/demo18")public void demo18(){AbstractMediator mediator = new ConcreteMediator();AbstractCollege c1,c2;c1 = new ConcreteCollege1();c2 = new ConcreteCollege2();mediator.register(c1);mediator.register(c2);c1.send();c2.send();}

不同对象之间的信息沟通 

3.8 迭代器模式

提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。

迭代器模式主要包含以下角色:

  • 抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
  • 具体聚合(Concrete Aggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
  • 抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含hasNext()、first()、next()等方法。
  • 具体迭代器(Concrete Iterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。

1)抽象聚合

public interface IteratorAggregate {public void add(Object obj);public void remove(Object obj);public Iterator getIterator();
}

2)具体聚合

public class ConcreteAggregate implements IteratorAggregate{private List<Object> list = new ArrayList<>();@Overridepublic void add(Object obj) {list.add(obj);}@Overridepublic void remove(Object obj) {list.remove(obj);}@Overridepublic Iterator getIterator() {return new ConcreteIterator(list);}
}

3)抽象迭代器

public interface Iterator {Object first();Object next();boolean hashNext();
}

4)具体迭代器


public class ConcreteIterator implements Iterator{private List<Object> list = new ArrayList<>();private int index = 0;public ConcreteIterator(List<Object> list){this.list = list;}@Overridepublic Object first() {index = 0;Object object = list.get(index);return object;}@Overridepublic Object next() {Object object = null;if(this.hashNext()){object = list.get(index++);}return object;}@Overridepublic boolean hashNext() {if(index >= list.size()){return false;}else {return true;}}
}

5)调用

    @GetMapping("/demo19")public void demo19(){IteratorAggregate ag = new ConcreteAggregate();ag.add("中山大学");ag.add("华南理工");ag.add("清华大学");ag.add("北大大学");Iterator it = ag.getIterator();while(it.hashNext()){Object ob = it.next();System.out.println(ob.toString() + "\n");}Object ob = it.first();System.out.println("\nFirst" + ob.toString());}

3.9 访问者模式

背景:有些集合对象中存在多种不同的元素,且每种元素也存在多种不同的访问者和处理方式。

访问者模式定义:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。 

访问者模式包含以下主要角色:

  • 抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作visit(),该操作中的参数类型标识了被访问的具体元素。
  • 具体访问者(Concrete Visitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
  • 抽象元素(Element)角色:声明一个包含接受操作accept()的接口,被接受的访问者对象作为accept()方法的参数。
  • 具体元素(Concrete Element)角色:实现抽象元素角色提供的accept()操作,其方法体通常都是visitor.visit(this),另外具体元素中可能还包含本身业务逻辑的相关操作。
  • 对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由List、Set、Map等聚合类实现。

1)抽象访问者

public interface AbstractVisitor {void visit(ConcreteElementA element);void visit(ConcreteElementB element);
}

2)具体访问者

//具体访问者A
public class ConcreteVisitorA implements AbstractVisitor{@Overridepublic void visit(ConcreteElementA element) {System.out.println("具体A访问者访问:" + element.Operation());}@Overridepublic void visit(ConcreteElementB element) {System.out.println("具体A访问者访问:" + element.Operation());}
}//具体访问者B
public class ConcreteVisitorB implements AbstractVisitor{@Overridepublic void visit(ConcreteElementA element) {System.out.println("具体B访问者访问:" + element.Operation());}@Overridepublic void visit(ConcreteElementB element) {System.out.println("具体B访问者访问:" + element.Operation());}
}

3)抽象元素

public interface Element {void accept(AbstractVisitor visitor);
}

4)具体元素

//具体元素A
public class ConcreteElementA implements Element{@Overridepublic void accept(AbstractVisitor visitor) {visitor.visit(this);}public String Operation(){return "具体元素A的操作!";}
}//具体元素B
public class ConcreteElementB implements Element{@Overridepublic void accept(AbstractVisitor visitor) {visitor.visit(this);}public String Operation(){return "具体元素B的操作!";}
}

5)对象结构元素

public class ObjectStructure {private List<Element> list = new ArrayList<Element>();public void accept(AbstractVisitor visitor){Iterator<Element> element = list.iterator();while(element.hasNext()){element.next().accept(visitor);}}public void add(Element element){list.add(element);}public void remove(Element element){list.remove(element);}
}

6)调用

    @GetMapping("/demo20")public void demo20(){ObjectStructure obs = new ObjectStructure();obs.add(new ConcreteElementA());obs.add(new ConcreteElementB());AbstractVisitor visitorA = new ConcreteVisitorA();obs.accept(visitorA);AbstractVisitor visitorB = new ConcreteVisitorB();obs.accept(visitorB);}

3.10  备忘录模式

备忘录模式(快照模式)能记录一个对象的内部状态,当用户后悔时能撤销当前操作,使数据恢复到它原先的状态。

备忘录模式的主要角色如下:

  • 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
  • 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
  • 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。

1)备忘录

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

2)发起人

public 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 restoreMemento(Memento m){this.setState(m.getState());}
}

3)管理者

public class Caretaker {private Memento memento;public void setMemento(Memento m){this.memento = m;}public Memento getMemento(){return memento;}
}

4)调用

    @GetMapping("/demo21")public void demo21(){Originator or = new Originator();Caretaker cr = new Caretaker();or.setState("S0");System.out.println("初始状态:" + or.getState());cr.setMemento(or.createMemento()); //保存状态or.setState("S1");System.out.println("新的状态:" + or.getState());or.restoreMemento(cr.getMemento()); //恢复状态System.out.println("恢复状态:" + or.getState());}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/138588.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为什么要学习去使用云服务器,外网 IP能干什么,MAC使用Termius连接阿里云服务器。保姆级教学

目录 引言 可能有人想问为什么要学习云服务器&#xff1f; &#xff08;获取Linux环境&#xff0c;获得外网IP) 二、安装教程 引言 可能有人想问为什么要学习云服务器&#xff1f; &#xff08;获取Linux环境&#xff0c;获得外网IP) 1.虚拟机&#xff08;下策&#xff09; …

Python零基础小白常遇到的问题总结

文章目录 一、注意你的Python版本1.print()函数2.raw_input()与input()3.比较符号&#xff0c;使用!替换<>4.repr函数5.exec()函数 二、新手常遇到的问题1、如何写多行程序&#xff1f;2、如何执行.py文件&#xff1f;3、and&#xff0c;or&#xff0c;not4、True和False…

LINUX入门篇【4】开发篇--开发工具vim的使用

前言&#xff1a; 从这一篇开始&#xff0c;我们将正式进入使用LINUX进行写程序和开发的阶段&#xff0c;可以说&#xff0c;由此开始&#xff0c;我们才开始真正去使用LINUX。 介绍工具&#xff1a; 1.LINUX软件包管理器yum&#xff1a; 1.yum的介绍&#xff1a; 在LINUX…

【教3妹学编程-算法题】2923. 找到冠军 I

3妹&#xff1a;2哥2哥&#xff0c;你看到新闻了吗&#xff1f;襄阳健桥医院院长 公然“贩卖出生证明”&#xff0c; 真是太胆大包天了吧。 2哥 : 我也看到新闻了&#xff0c;7人被采取刑事强制措施。 就应该好好查查他们&#xff0c; 一查到底&#xff01; 3妹&#xff1a;真的…

Oracle(18)Auditing

文章目录 一、基础知识1、审计介绍2、Auditing Types 审计类型3、Auditing Guidelines 审计准则4、Auditing Categories 审核类别5、Database Auditing 数据库审计6、Auditing User SYS 审计sys用户7、Getting Auditing Informatio 获取审计信息8、获取审计记录通知 二、基础操…

赛氪助力全国大学生数学竞赛山东赛区圆满举办

近日&#xff0c;全国大学生数学竞赛山东赛区比赛有序进行&#xff0c;赛氪已连续6年助力本项赛事蓬勃发展。在中国高等教育学会高校竞赛评估与管理体系研究专家工作组发布的《2022全国普通高校大学生竞赛分析报告》中&#xff0c;本赛事荣登观察目录。 全国大学生数学竞赛旨在…

基于STC12C5A60S2系列1T 8051单片机串口通信信应用

基于STC12C5A60S2系列1T 8051单片机串口通信应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机串口通信介绍STC12C5A60S2系列1T 8051单片机串口通信的结构基于STC12C5A60S2系列1T 8051单片机串口通信的特殊功能寄存器列表基于STC12C5A60S2系列1T 8051单片…

高校教务系统登录页面JS分析——长沙理工大学教务系统

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文将是本专栏最后一篇文章&#xff0c;我看了绝大多数高…

【代码随想录】算法训练计划18

1、513. 找树左下角的值 题目&#xff1a; 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 思路&#xff1a; 递归&#xff0c;规则&#xff0c;基本可以自己写出来 var maxDepth int var res int fun…

Spring Gateway基础知识总结

本文主要总结Spring Gateway的基础用法&#xff0c;内容包括网关、Spring Gateway工作流程、Spring Cloud Gateway搭建、路由配置方式、负载均衡实现、断言工厂这几个部分 目录 1. 网关 1.1 网关介绍 1.2 网关对比 1.3 Spring Gateway 1.4 核心概念 1.6 总结 2. Spring …

React进阶之路(二)-- 组件通信、组件进阶

文章目录 组件通信组件通信的意义父传子实现props说明子传父实现兄弟组件通信跨组件通信Context通信案例 React组件进阶children属性props校验组件生命周期 组件通信 组件通信的意义 组件是独立且封闭的单元&#xff0c;默认情况下组件只能使用自己的数据&#xff08;state&a…

【C++破局】C++内存管理之new与deleted剖析

​作者主页 &#x1f4da;lovewold少个r博客主页 ⚠️本文重点&#xff1a;c内存管理部分知识点梳理 &#x1f449;【C-C入门系列专栏】&#xff1a;博客文章专栏传送门 &#x1f604;每日一言&#xff1a;花有重开日&#xff0c;人无再少年&#xff01; 目录 C/C的内存分配机…

Git 命令详解

系列文章目录 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 C技能系列 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the future of dream we…

【Python】Python爬虫使用代理IP的实现

前言 在爬虫的过程中&#xff0c;我们经常会遇到需要使用代理IP的情况。比如&#xff0c;针对目标网站的反爬机制&#xff0c;需要通过使用代理IP来规避风险。因此&#xff0c;本文主要介绍如何在Python爬虫中使用代理IP。 一、代理IP的作用 代理IP&#xff0c;顾名思义&…

JVM虚拟机:垃圾回收器之Parallel Old(老年代)

本文重点 本文将学习老年代的另外一种垃圾回收器Parallel Old(PO)&#xff0c;这是一种用于老年代的并行化垃圾回收器&#xff0c;它使用标记整理算法进行垃圾回收。 历史 在1.6之前&#xff0c;新生代使用Parallel Scavenge只能搭配老年代的Serial Old收集器&#xff0c;而…

Ubuntu22.04 下 NFS 相关问题与完整配置(客户机 MacOS)

categories: [Linux-Shell] tags: Linux NFS 写在前面 最近折腾一下 NFS, 先白嫖一顿华子云的 1 个月服务器, 2C4G 感觉不错了, 但NFS 配置起来还是有点难度, 主要还是随机分配的端口配置方面比较恶心. server环境: 华为云 2C4G Ubuntu22.04 client环境: MacOS M1 with brew …

小程序多文件上传 Tdesign

众所周知&#xff0c;小程序文件上传还是有点麻烦的&#xff0c;其实主要还是小程序对的接口有诸多的不便&#xff0c;比如说&#xff0c;文件不能批量提交&#xff0c;只能一个个的提交&#xff0c;小程序的上传需要专门的接口。 普通的小程序的页面也比普通的HTML复杂很多 现…

Java,多线程,线程安全的懒汉式、死锁、ReentrantLock的使用以及一些知识点补充

关于线程安全地懒汉式有以下几种方式&#xff1a; /*** 实现线程安全的懒汉式*/ public class BankTest {Bank b1 null;Bank b2 null;public static void main(String[] args){BankTest bb new BankTest();Thread t1 new Thread(){Overridepublic void run(){bb.b1 Bank.…

安卓RadioButton设置图片大小

RadioButton都不陌生&#xff0c;一般我们都会设置图片在里面&#xff0c;这就涉及一个问题&#xff0c;图片的大小。如果图片过大&#xff0c;效果很不理想。搜了很多方法&#xff0c;都不理想。无奈只能自己研究了 代码如下&#xff1a; 1&#xff0c;一个简单的 RadioButt…

IBM Qiskit量子机器学习速成(一)

声明&#xff1a;本篇笔记基于IBM Qiskit量子机器学习教程的第一节&#xff0c;中文版译文详见&#xff1a;https://blog.csdn.net/qq_33943772/article/details/129860346?spm1001.2014.3001.5501 概述 首先导入关键的包 from qiskit import QuantumCircuit from qiskit.u…