盐城网站建设与网页制作,网站建设基础流程摘要,适合个人做的跨境电商,育才网站建设软件设计模式是前辈们代码设计经验的总结#xff0c;可以反复使用。设计模式共分为3大类#xff0c;创建者模式(6种)、结构型模式(7种)、行为型模式(11种)#xff0c;一共24种设计模式#xff0c;软件设计一般需要满足7大基本原则。下面通过5章的学习一起来看看设计模式的魅…软件设计模式是前辈们代码设计经验的总结可以反复使用。设计模式共分为3大类创建者模式(6种)、结构型模式(7种)、行为型模式(11种)一共24种设计模式软件设计一般需要满足7大基本原则。下面通过5章的学习一起来看看设计模式的魅力吧。
行为模式(11种)本质是描述类与对象协助完成单个对象无法完成的任务以及怎么分配职责。
包括模板方法、策略、命令、责任链、状态、观察者、中介者模式、迭代器、访问者、备忘录、解释器。
目录
1.中介者模式
2.迭代器模式
3.访问者模式
4.备忘录模式
5.解释器模式 1.中介者模式
定义中介者模式又称为调停模式定义一个中介角色来封装一系列对象的交互操作使得原有对象之间耦合度减小。
中介者模式包含以下角色
01.抽象中介者中介者接口提供同事对象注册与转发同事对象的抽象方法。
02.具体中介者协调各个同事之间的关系。
03.抽象同事类定义同事类的接口保存中介者对象提供同事对象交互的抽象方法。
04.具体同事类抽象同事类的实现者。
中介者模式的优缺点及使用场景
优点松散耦合、集中控制。
缺点同事类比较多的情况下中介者的职责将变得复杂而庞大。
使用场景系统中对象存在复杂的引用关系系统结构混乱且难以理解。
下面通过一个租房的案例学习一下中介者模式房主和租客是同事类中介就是中介类。
1.首先定义一个抽象同事类包含房主与租客的名字以及中介对象。
/*** author nuist__NJUPT* ClassName Person* description: 抽象同事类* date 2024年02月03日*/
public abstract class Person {protected String name ;protected Mediator mediator ;public Person(String name, Mediator mediator) {this.name name;this.mediator mediator;}
}
2.然后定义一个抽象的中介对象用于和房主以及租客进行沟通。
/*** author nuist__NJUPT* ClassName Mediator* description: 抽象中介者类* date 2024年02月03日*/
public abstract class Mediator {public abstract void contact(String message, Person person) ;
}
3.定义具体的同事角色类即租客类与房主类需要获取信息并与中介进行沟通。
/*** author nuist__NJUPT* ClassName HouseOwner* description: 具体的同事角色类* date 2024年02月03日*/
public class HouseOwner extends Person {public HouseOwner(String name, Mediator mediator) {super(name, mediator);}// 和中介进行沟通public void contact(String message){mediator.contact(message, this);}// 获取信息public void getMessage(String message){System.out.println(房东 name 获取到的信息 message);}
}/*** author nuist__NJUPT* ClassName Tenant* description: 具体同事角色类* date 2024年02月03日*/
public class Tenant extends Person {public Tenant(String name, Mediator mediator) {super(name, mediator);}// 和中介进行沟通public void contact(String message){mediator.contact(message, this);}// 获取信息public void getMessage(String message){System.out.println(租房者 name 获取到的信息 message);}}4.定义具体的中介类用于和房主以及租客进行沟通。
/*** author nuist__NJUPT* ClassName MediatorStructure* description: 具体的中介者类* date 2024年02月03日*/
public class MediatorStructure extends Mediator {// 聚合同事角色类房主和租客private HouseOwner houseOwner ;private Tenant tenant ;public HouseOwner getHouseOwner() {return houseOwner;}public void setHouseOwner(HouseOwner houseOwner) {this.houseOwner houseOwner;}public Tenant getTenant() {return tenant;}public void setTenant(Tenant tenant) {this.tenant tenant;}// 和中介沟通public void contact(String message, Person person){if(person houseOwner){tenant.getMessage(message);}else if(person tenant){houseOwner.getMessage(message);}}}
5.最后创建测试类创建中介创建房主与租客使中介知道该房主与租客最后通过中介进行沟通。
/*** author nuist__NJUPT* ClassName Client* description: 客户端测试类* date 2024年02月03日*/
public class Client {public static void main(String[] args) {// 创建中介对象MediatorStructure mediatorStructure new MediatorStructure() ;// 创建房主与租客对象HouseOwner houseOwner new HouseOwner(肥婆, mediatorStructure) ;Tenant tenant new Tenant(小王, mediatorStructure) ;// 中介需要知道具体的房主与租客mediatorStructure.setHouseOwner(houseOwner);mediatorStructure.setTenant(tenant);// 通过中介完成房主与租客进行沟通tenant.contact(请问有单间可以出租吗);houseOwner.contact(有的...);}
}2.迭代器模式
定义提供一个对象来访问聚合对象中的一系列数据而不暴露聚合对象的内部表示。
迭代器模式主要包含如下角色 01.抽象聚合角色定义元素操作以及迭代器对象的接口。
02.具体聚合角色实现抽象聚合角色返回一个具体的迭代器对象。
03.抽象迭代器角色定义访问和遍历聚合元素的接口包含next()等方法。
04.具体迭代器角色实现抽象迭代器类并重写相应的抽象方法遍历与访问聚合元素。
迭代器模式的优缺点及使用场景
优点支持以不同方式遍历一个聚合对象简化了聚合类的设计满足开闭原则。
缺点增加了类的数目在一定程度上增加了系统的复杂度。
使用场景遍历聚合对象提供统一接口不暴露内部实现细节。在java的集合中使用了迭代器模式使用迭代器可以遍历集合元素。
下面定义一个存储学生对象的容器对象将遍历该容器的功能交给迭代器实现。
1.定义一个学生对象包含姓名合编号。 /*** author nuist__NJUPT* ClassName Student* description: 学生对象* date 2024年02月03日*/
public class Student {private String name ;private String number ;public String getName() {return name;}public void setName(String name) {this.name name;}public String getNumber() {return number;}public void setNumber(String number) {this.number number;}Overridepublic String toString() {return Student{ name name \ , number number \ };}public Student(String name, String number) {this.name name;this.number number;}public Student() {}
}
2.定义聚合接口及其实现类用于用于添加/删除学生对象以及获取迭代器对象。
/*** author nuist__NJUPT* InterfaceName StudentAggregate* description: 抽象聚合角色* date 2024年02月03日*/
public interface StudentAggregate {// 添加学生void addStudent(Student student) ;// 删除学生void removeStudent(Student student) ;// 获取迭代器对象StudentIterator getStudentIterator() ;
}import java.util.ArrayList;
import java.util.List;/*** author nuist__NJUPT* ClassName StudentAggregateImpl* description: 具体聚合角色* date 2024年02月03日*/
public class StudentAggregateImpl implements StudentAggregate {private ListStudent list new ArrayListStudent() ;public void addStudent(Student student) {list.add(student) ;}public void removeStudent(Student student) {list.remove(student) ;}public StudentIterator getStudentIterator() {return new StudentIteratorImpl(list);}
}3.定义迭代器接口及其实现类用于遍历迭代器元素。
/*** author nuist__NJUPT* InterfaceName StudentIterator* description: 抽象迭代器角色接口* date 2024年02月03日*/
public interface StudentIterator {// 判断是否还有元素boolean hasNext() ;// 获取下一个元素Student next() ;}
import java.util.List;/*** author nuist__NJUPT* ClassName StudentIteratorImpl* description: 具体迭代器角色* date 2024年02月03日*/
public class StudentIteratorImpl implements StudentIterator {ListStudent list ;private int position 0 ;public StudentIteratorImpl(ListStudent list) {this.list list;}public boolean hasNext() {return position list.size() ;}public Student next() {return list.get(position);}
}4.定义客户端测试类通过向聚合对象添加学生对象通过获取迭代器对象遍历元素。 /*** author nuist__NJUPT* ClassName Client* description: 客户端测试类* date 2024年02月03日*/
public class Client {public static void main(String[] args) {// 创建聚合对象StudentAggregate studentAggregate new StudentAggregateImpl() ;// 添加学生对象studentAggregate.addStudent(new Student(张三, 1));studentAggregate.addStudent(new Student(王五, 2));studentAggregate.addStudent(new Student(李四, 3));// 获取迭代器对象StudentIterator iterator studentAggregate.getStudentIterator();// 通过迭代器对象遍历while (iterator.hasNext()){System.out.println(iterator.next().toString());}}}3.访问者模式
定义封装一些作用于某种数据结构的各种操作在不改变数据结构的前提下定义作用于这些元素的新操作。
访问者模式包含以下角色
01.抽象访问者角色定义了对每个元素的访问行为。
02.具体访问者角色定义了对每个元素类访问时所产生的具体行为。
03.抽象元素角色定义一个接收访问者的方法。
04.具体元素角色定义一个接收方法的具体实现。 05.对象结构定义对象结构包含一组元素及其迭代方式供访问者访问。
访问者模式的优缺点及使用场景
优点扩展性好复用性好通过访问者来分离无关行为。
缺点违背依赖倒转原则访问者是依赖具体而不是依赖抽象。 使用场景对象结构相对稳定但是操作算法经常变化。
下面通过给宠物喂食的案例学习一下访问者模式。其中各个类对应的角色如下
抽象访问者角色给宠物喂食的人
具体访问者角色主人、其它人
抽象元素角色动物角色
具体元素角色宠物狗、宠物猫
结构对象角色主人家
1.首先定义一个抽象元素角色定义由访问者访问的方法。
/*** author nuist__NJUPT* InterfaceName Animal* description: 抽象元素角色类* date 2024年02月04日*/
public interface Animal {// 接受访问者访问void accept(Person person) ;}
2.定义两个具体元素角色实现抽象元素角色接口并重写相应的接口方法。 /*** author nuist__NJUPT* ClassName Dog* description: 具体元素角色* date 2024年02月04日*/
public class Dog implements Animal{public void accept(Person person) {person.feedDog(this);System.out.println(好吃汪汪汪...);}
}/*** author nuist__NJUPT* ClassName Cat* description: 具体元素角色类* date 2024年02月04日*/
public class Cat implements Animal{public void accept(Person person) {person.feedCat(this);System.out.println(好吃喵喵喵...);}
}
3.定义抽象访问者类类中定义访问方法。 /*** author nuist__NJUPT* InterfaceName Person* description: 抽象访问者角色* date 2024年02月04日*/
public interface Person {// 给猫喂食void feedCat(Cat cat) ;// 给狗喂食void feedDog(Dog dog) ;}4.定义具体访问者类并实现抽象访问者接口重写接口方法。 /*** author nuist__NJUPT* ClassName Owner* description: 具体访问者* date 2024年02月04日*/
public class Owner implements Person {public void feedCat(Cat cat) {System.out.println(主人喂宠物猫);}public void feedDog(Dog dog) {System.out.println(主人喂宠物狗);}
}/*** author nuist__NJUPT* ClassName Someone* description: 具体访问者* date 2024年02月04日*/
public class Someone implements Person {public void feedCat(Cat cat) {System.out.println(其它人喂宠物猫);}public void feedDog(Dog dog) {System.out.println(其它人喂宠物狗);}}
5.定义对象结构类用于添加元素并为访问者类提供访问对象的方法。
import java.util.ArrayList;
import java.util.List;/*** author nuist__NJUPT* ClassName Home* description: 对象结构类* date 2024年02月04日*/
public class Home {// 定义一个集合对象用来存储元素对象ListAnimal animals new ArrayListAnimal() ;// 添加元素public void addAnimal(Animal animal){animals.add(animal) ;}// 提供访问者访问元素对象的方法public void action(Person person){for(Animal animal : animals){animal.accept(person);}}}6.定义客户端测试类验证访问者模式。 /*** author nuist__NJUPT* ClassName Client* description: 客户端测试类* date 2024年02月04日*/
public class Client {public static void main(String[] args) {// 创建结构对象Home home new Home() ;// 添加元素对象home.addAnimal(new Dog());home.addAnimal(new Cat());// 创建访问者对象Owner owner new Owner() ;// 结构对象提供访问者对象访问相应的元素home.action(owner);}
}4.备忘录模式
定义备忘录模式又称为快照模式在不破坏封装性的前提下捕获一个对象的内部状态并在外部保存这个对象的内部状态当需要使用到的时候可以快速恢复到保存的状态。
备忘录模式的主要角色如下 01.发起人角色记录当前时刻的内部状态信息提供创建备忘录记录和恢复备忘录记录的功能。
02.备忘录角色存储发起人的内部状态信息在需要的时候将这个状态传递给发起人。
03.管理者角色对备忘录进行管理提供保存与获取备忘录的功能不能更改备忘录内部细节。
备忘录模式的优缺点及使用场景 优点提供了状态恢复机制实现了内部状态的封装也符合单一职责原则。
缺点资源多的情况下资源消耗大。
使用场景需要保存与恢复数据提供一个可以回滚的场景。
备忘录模式有黑箱备忘录和白箱备忘录模式白箱备忘录模式是破坏封装性的即备忘录管理者能构修改备忘录内部的细节。
下面通过一个游戏案例学习备忘录模式一个游戏角色有生命力、攻击力、防御力等数据在打boss前和打boss后一定会不一样玩家在跟boss决斗不理想的情况下允许恢复到之前的状态。
1.首先先一下白箱备忘录模式定义一个游戏角色即发起人对象。 /*** author nuist__NJUPT* ClassName GameRole* description: 游戏角色类-发起人对象* date 2024年02月04日*/
public class GameRole {// 攻击力private int vit ;// 防御力private int def ;// 生命力private int atk ;// 初始化内部状态public void initState(){this.vit 100 ;this.def 100 ;this.atk 100 ;}// 战斗public void fight(){this.vit 0 ;this.atk 0 ;this.def 0 ;}// 保存角色状态功能public RoleStateMemento saveState(){return new RoleStateMemento(vit, def, atk) ;}// 恢复角色状态public void recoveryState(RoleStateMemento roleStateMemento){// 将备忘录中存储的对象状态赋值到当前对象this.vit roleStateMemento.getVit() ;this.def roleStateMemento.getDef() ;this.atk roleStateMemento.getAtk() ;}// 展示状态功能public void stateDisplay(){System.out.println(角色生命力: vit);System.out.println(角色攻击力 atk);System.out.println(角色防御力 def);}public int getVit() {return vit;}public void setVit(int vit) {this.vit vit;}public int getDef() {return def;}public void setDef(int def) {this.def def;}public int getAtk() {return atk;}public void setAtk(int atk) {this.atk atk;}
}2.定义备忘录角色用于保存发起人角色的状态。
/*** author nuist__NJUPT* ClassName RoleStateMemento* description: 备忘录角色类* date 2024年02月04日*/
public class RoleStateMemento {// 攻击力private int vit ;// 防御力private int def ;// 生命力private int atk ;public RoleStateMemento(int vit, int def, int atk) {this.vit vit;this.def def;this.atk atk;}public RoleStateMemento() {}public int getVit() {return vit;}public void setVit(int vit) {this.vit vit;}public int getDef() {return def;}public void setDef(int def) {this.def def;}public int getAtk() {return atk;}public void setAtk(int atk) {this.atk atk;}
}
3.定义管理者角色用于管理备忘录备忘录提供宽接口即提供具体备忘录实现类给管理者管理
/*** author nuist__NJUPT* ClassName RoleStateCaretaker* description: 管理者类* date 2024年02月04日*/
public class RoleStateCaretaker {// 声明备忘录类对象private RoleStateMemento roleStateMemento ;public RoleStateMemento getRoleStateMemento() {return roleStateMemento;}public void setRoleStateMemento(RoleStateMemento roleStateMemento) {this.roleStateMemento roleStateMemento;}}4.最后定义测试类测试白箱备忘录模式。
/*** author nuist__NJUPT* ClassName Client* description: 客户端测试类-白箱备忘录模式* date 2024年02月04日*/
public class Client {public static void main(String[] args) {System.out.println(-----------------大战Boss前-------------------) ;// 创建发起人角色GameRole gameRole new GameRole() ;gameRole.initState();gameRole.stateDisplay();// 创建备忘录管理者管理备忘录RoleStateCaretaker roleStateCaretaker new RoleStateCaretaker() ;roleStateCaretaker.setRoleStateMemento(gameRole.saveState());System.out.println(-----------------大战Boss后-------------------) ;// 战斗gameRole.fight();gameRole.stateDisplay();System.out.println(-----------------恢复到之前的状态-------------------) ;gameRole.recoveryState(roleStateCaretaker.getRoleStateMemento());gameRole.stateDisplay();}
}还是这个案例下面我们看一下黑箱备忘录模式该模式是将备忘录实现类放到发起人角色类的内部通过提供一个抽象接口给管理者管理。
1.定义发起人类对象在发起人对象内部定义备忘录类对象。
/*** author nuist__NJUPT* ClassName GameRole* description: 将备忘录角色类定义在发起者角色类的内部* date 2024年02月04日*/
public class GameRole {// 攻击力private int vit ;// 防御力private int def ;// 生命力private int atk ;// 初始化内部状态public void initState(){this.vit 100 ;this.def 100 ;this.atk 100 ;}// 战斗public void fight(){this.vit 0 ;this.atk 0 ;this.def 0 ;}// 保存角色状态功能public Memento saveState(){return new RoleStateMemento(vit, def, atk) ;}// 恢复角色状态public void recoveryState(Memento memento){RoleStateMemento roleStateMemento (RoleStateMemento) memento;// 将备忘录中存储的对象状态赋值到当前对象this.vit roleStateMemento.getVit() ;this.def roleStateMemento.getDef() ;this.atk roleStateMemento.getAtk() ;}// 展示状态功能public void stateDisplay(){System.out.println(角色生命力: vit);System.out.println(角色攻击力 atk);System.out.println(角色防御力 def);}public int getVit() {return vit;}public void setVit(int vit) {this.vit vit;}public int getDef() {return def;}public void setDef(int def) {this.def def;}public int getAtk() {return atk;}public void setAtk(int atk) {this.atk atk;}public class RoleStateMemento implements Memento{// 攻击力private int vit ;// 防御力private int def ;// 生命力private int atk ;public RoleStateMemento(int vit, int def, int atk) {this.vit vit;this.def def;this.atk atk;}public RoleStateMemento() {}public int getVit() {return vit;}public void setVit(int vit) {this.vit vit;}public int getDef() {return def;}public void setDef(int def) {this.def def;}public int getAtk() {return atk;}public void setAtk(int atk) {this.atk atk;}}
}
2.对外提供一个备忘录抽象接口由管理者管理。
/*** author nuist__NJUPT* InterfaceName Memento* description: 备忘录接口-对外提供窄接口* date 2024年02月04日*/
public interface Memento {}3.声明管理者类管理备忘录对象。 /*** author nuist__NJUPT* ClassName RoleStateCaretaker* description: 管理者类-只管理备忘录的接口抽象不管理具体内部实现类细节* date 2024年02月04日*/
public class RoleStateCaretaker {// 声明备忘录类对象private Memento memento ;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento memento;}
}4.定义客户端测试类测试黑盒备忘录模式。
/*** author nuist__NJUPT* ClassName Client* description: 客户端测试类-黑箱备忘录模式* date 2024年02月04日*/public class Client {public static void main(String[] args) {System.out.println(-----------------大战Boss前-------------------) ;// 创建发起人角色GameRole gameRole new GameRole() ;gameRole.initState();gameRole.stateDisplay();// 创建备忘录管理者管理备忘录RoleStateCaretaker roleStateCaretaker new RoleStateCaretaker() ;roleStateCaretaker.setMemento(gameRole.saveState());System.out.println(-----------------大战Boss后-------------------) ;// 战斗gameRole.fight();gameRole.stateDisplay();System.out.println(-----------------恢复到之前的状态-------------------) ;gameRole.recoveryState(roleStateCaretaker.getMemento());gameRole.stateDisplay();}
}5.解释器模式
定义给定一个语言定义它的文法表示并定义一个解释器这个解释器使用该标识来解释语言中的句子。
解释器模式包含以下角色
01.抽象表达式角色定义解释器接口约定解释器的解释操作。
02.终结符表达式角色抽象表达式的子类用来实现文法中与终结符相关的操作。
03.非终结符表达式角色抽象表达式的子类用来实现文法中与非终结符相关的操作。
04.环境角色通常包含各个解释器需要的数据或是公共的功能。
05.客户端将需要分析的句子或者表达式转换成使用解释器对象描述的抽象语法树。
解释器模式的优缺点及使用场景
优点易于改变与扩展文。
缺点对于复杂的文法难以维护。 使用场景当语言的文法较为简单且执行效率不是关键问题的时候。
通过实现用于加减法的案例来学习解释器模式具体如下
1.首先定义抽象表达式类定义解释器接口。 /*** author nuist__NJUPT* ClassName AbstractExpression* description: 抽象表达式角色* date 2024年02月04日*/
public abstract class AbstractExpression {public abstract int intercept(Context context) ;}2.定义三个具体表达式角色是抽象表达式的子类。
/*** author nuist__NJUPT* ClassName Plus* description: 加法表达式角色* date 2024年02月04日*/
public class Plus extends AbstractExpression {// 号左边的表达式private AbstractExpression left ;// 号右边的表达式private AbstractExpression right ;public Plus(AbstractExpression left, AbstractExpression right) {this.left left;this.right right;}public int intercept(Context context) {// 将左边表达式的结果与右边表达式的结果进行相加return left.intercept(context) right.intercept(context);}Overridepublic String toString() {return Plus{ left left , right right };}
}/*** author nuist__NJUPT* ClassName Minus* description: 减法表达式类* date 2024年02月04日*/
public class Minus extends AbstractExpression {// -号左边的表达式private AbstractExpression left ;// -号右边的表达式private AbstractExpression right ;public Minus(AbstractExpression left, AbstractExpression right) {this.left left;this.right right;}public int intercept(Context context) {// 将左边表达式的结果与右边表达式的结果进行相减return left.intercept(context) - right.intercept(context);}Overridepublic String toString() {return Plus{ left left , right right };}
}/*** author nuist__NJUPT* ClassName Variable* description: TODO* date 2024年02月04日*/
public class Variable extends AbstractExpression {// 声明存储变量名的成员变量private String name ;public Variable(String name){this.name name ;}public int intercept(Context context) {// 直接返回变量的值return context.getValue(this);}Overridepublic String toString() {return Variable{ name name \ };}
}3.定义环境角色用于对变量进行操作。 import java.util.HashMap;
import java.util.Map;/*** author nuist__NJUPT* ClassName Context* description: 环境角色类* date 2024年02月04日*/
public class Context {// 定义一个Map集合用来存储变量及其对应的值private MapVariable,Integer map new HashMapVariable, Integer() ;// 添加变量的功能public void assign(Variable variable, Integer value){map.put(variable, value) ;}// 根据变量获取相应的值public int getValue(Variable variable){return map.get(variable) ;}}4.最后定义测试类测试解释器模式。
/*** author nuist__NJUPT* ClassName Client* description: 客户端测试类* date 2024年02月04日*/
public class Client {public static void main(String[] args) {// 创建环境对象Context context new Context() ;// 创建多个变量Variable a new Variable(a) ;Variable b new Variable(b) ;Variable c new Variable(c) ;Variable d new Variable(d) ;// 将变量存储到环境中context.assign(a,1);context.assign(b,2);context.assign(c,3);context.assign(d,4);// 获取抽象语法树AbstractExpression abstractExpression new Minus(a, new Plus(new Minus(b, c), d));// 解释int intercept abstractExpression.intercept(context);System.out.println(intercept);}
}