设计模式
上午考下午也要考
最爱考“意图”、”类型“、”结构“、”适用性“
目的:为了复用成功的设计和体系结构
按设计模式的目的可分为三大类:
工厂类:生抽原单(生抽原来是单身)
结构类:适配桥 组装外观 享(元)代理
创建型模式5
与对象的创建有关,抽象了实例化过程
在这些模式中有两个不断出现的主旋律:
第一,它们都将关于该系统使用哪些具体的类的信息封装起来
第二,它们隐藏了这些类的实例是如何被创建和放在一起的
简单工厂模式 (属于创建型模式,但不属于23种设计模式之一)
- 定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
- 在简单工厂模式中用于被创建实例的方法通常为静态方法
- 即需要什么产品就传入产品对应的参数,就可以获取所需要的产品对象,而无需知道其实现过程
- 三类角色:
- 工厂(核心):负责实现创建所有产品的内部逻辑,工厂类可以被外界直接调用,创建所需对象
- 抽象产品:工厂类所创建的所有对象的父类,封装了产品对象的公共方法,所有的具体产品为其子类对象
- 具体产品:简单工厂模式的创建目标,所有被创建的对象都是某个具体类的实例,它要实现抽象产品中声明的抽象方法
// 直接调用
public class FactoryMethod {
public static void main(String[] args) {
Product productA = Factory.createProduct("A");
productA.info();
Product productB = Factory.createProduct("B");
productB.info();
}
}
// 工厂
class Factory{
public static Product createProduct(String type){
Product product = null;
switch(type){
case "A":
product = new ProductA();
break;
case "B":
product = new ProductB();
case "defalut":
System.out.println("没有"+type+"类型的产品!");
break;
}
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");
}
}
工厂方法模式
- 意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类
- 结构如下图:
-
适用性:
- 当一个类 不知道 它所必须创建的对象的类的时候
- 当一个类希望由 它的子类 来 指定 它所创建的对象的时候
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候
-
代码展示:
// 直接调用
public class FactoryMethod {
public static void main(String[] args) {
//编译看左边,运行看右边
Factory factoryA = new FactoryA();
Product productA = factoryA.createProduct();
productA.info();
Factory factoryB = new FactoryB();
Product productB = factoryB.createProduct();
productB.info();
}
}
// 接口1、factory
interface Factory{
// 由实现接口的子类实例化对象
public Product createProduct();
}
// 接口实现——具体工厂
class FactoryA implements Factory{
@Override
public Product createProduct(){
return new ProductA();
}
}
class FactoryB implements Factory{
@Override
public Product createProduct(){
return new ProductB();
}
}
// 接口2、产品
interface Product{
public void info();
}
// 接口实现——具体产品
class ProductA implements Product {
@Override
public void info() {
System.out.println("产品信息是:A");
}
}
class ProductB implements Product{
@Override
public void info(){
System.out.println("产品信息是:B");
}
}
抽象工厂模式
- 意图:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
- 结构:
- 适用于:
- 一个系统要独立于它的产品的创建、组合 和表示时。
- 一个系统要由多个产品系列中的一个来配置时。
- 当强调一系列相关的产品对象的设计以便进行联合使用时。
- 当提供一个产品类库,只想显示它们的接口而不是实现时。
- 代码展示:
// 直接调用
public class FactoryMethod {
public static void main(String[] args) {
Factory factory1 = new Factory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.info();
productB1.info();
Factory factory2 = new Factory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.info();
productB2.info();
}
}
// 工厂接口
interface Factory {
public ProductA createProductA();
public ProductB createProductB();
}
class Factory1 implements Factory{
@Override
public ProductA createProductA(){
return new ProductA1();
}
@Override
public ProductB createProductB(){
return new ProductB1();
}
}
class Factory2 implements Factory{
@Override
public ProductA2 createProductA(){
return new ProductA2();
}
@Override
public ProductB createProductB(){
return new ProductB2();
}
}
// 产品A接口
interface ProductA{
public void info();
}
// 接口实现——具体产品
class ProductA1 implements ProductA {
@Override
public void info() {
System.out.println("产品信息是:A1");
}
}
class ProductA2 implements ProductA{
@Override
public void info(){
System.out.println("产品信息是:A2");
}
}
// 产品B接口
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");
}
}
一个工厂假如只能产生一类产品的话——工厂模式
一个工厂假如能产生多类产品的话——抽象工厂模式
生成器模式
- 意图:将一个复杂对象的 构建 与 它的表示 分离,使得同样的构建过程可以创建不同的表示
- 结构:
- 适用于:
- 当创建复杂对象的算法应该独立于该对象的组成部件以及它们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时。
- 代码展示:
import java.util.*;
public class FactoryMethod {
public static void main(String[] args) {
Director director = new Director(); // 实例化 发号施令的人——老大
Builder builder1 = new Builder1(); //实例化 做产品的人——工匠
director.Construct(builder1); // 老大指定工匠去做产品
Product product1 = builder1.getResult(); //工匠从产品中获得其组件(零件)
product1.show();
}
}
// 发号施令的老大
class Director{
public void Construct(Builder builder){
builder.BuildPart();
}
}
// 做产品的工匠
abstract class Builder{
public abstract void BuildPart();
public abstract Product getResult();
}
class Builder1 extends Builder {
Product product = new Product();
@Override
public void BuildPart(){
product.Add("A");
product.Add("B");
product.Add("C");
}
@Override
public Product getResult(){
return product;
}
}
class Builder2 extends Builder {
Product product = new Product();
@Override
public void BuildPart(){
product.Add("E");
product.Add("F");
product.Add("G");
}
@Override
public Product getResult(){
return product;
}
}
// 产品
class Product{
List<String> parts = new ArrayList<String>();
public void Add(String part){
parts.add(part);
}
public void show(){
System.out.println("产品的组成:");
for (String s:parts)
System.out.print(s);
System.out.print("\n");
}
}
原型模式
- 意图:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象
- 结构:
- 适用于:
- 当一个系统应该独立于它的产品构建、构成和表示时。
- 当要实例化的类是在运行时刻指定时,例如,通过动态装载。
- 为了避免创建一个与产品类层次平行的工厂类层次时。
- 当一个类的实例只能有几个不同状态组合中的一种时,建立相应数目的原型并克隆它们,可能比每次用合适的状态手工实例化该类更方便一些
- 代码展示:
public class FactoryMethod {
public static void main(String[] args) {
Product product1 = new Product(6666,11.9);
System.out.println(product1.getId()+","+product1.getPrice());
Product product2 = (Product) product1.Clone(); // 直接克隆1的参数
System.out.println(product2.getId()+","+ product2.getPrice());
}
}
interface Prototype{
public Object Clone();
}
class Product implements Prototype {
private int id;
private double price;
public Product() {} // 无参构造
public Product(int id,double price){ // 有参构造
this.id = id;
this.price = price;
}
public int getId(){
return id;
}
public double getPrice(){
return price;
}
@Override
public Object Clone() {
Product Object = new Product();
Object.id = this.id;
Object.price = this.price;
return Object;
}
}
单例模式
- 意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。(只考上午题)
- 结构:
- 适用于:
- 当类只能由一个实例而且客户可以从一个众所周知的访问点访问它时。
- 当这个唯一的实例应该是通过子类化可扩展的,并且客户无须更改代码就能使用一个扩展的实例时
- 代码展示:
public class FactoryMethod {
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
Singleton singleton3 = Singleton.getInstance();
// 访问该单例的全局访问点getInstance()
System.out.println(singleton1.getNumber()+","+singleton2.getNumber()+","+singleton3.getNumber());
}
}
class Singleton{
private static Singleton instance = new Singleton();
private Singleton(){}
// 全局访问点
public static Singleton getInstance(){
return instance;
}
private int number = 2024;
public void setNumber(int number){
this.number=number;
}
public int getNumber(){
return number;
}
}
结构性模式7
处理类或对象的组合
在结构性模式中,适配器可以是类模式,也可以是对象模式
适配器模式
- 意图:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作(转接口)
- 结构:对象适配器依赖于对象组合
- 适用于:
- 想使用一个已经存在的类,而它的接口不符合要求。
- 想创建一个可以服用的类,该类可以与其他不相关类或不可预见的类(即那些接口可能不一定兼容)协同工作。
- (仅适用于对象Adapter)想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口
- 代码展示:
public class FactoryMethod {
public static void main(String[] args) {
USB usb = new Adapter();
usb.Request();
}
}
// 需USB接口
class USB{
public void Request(){
System.out.println("USB数据线");
}
}
// 适配器(转接口:将TypeC——>USB)
class Adapter extends USB{
private TypeC typeC = new TypeC();
@Override
public void Request(){
typeC.SpecificRequest();
}
}
// 但只有TypeC接口
class TypeC{
public void SpecificRequest(){
System.out.println("TypeC数据线");
}
}
桥接模式
- 意图:将抽象部分与其实现部分分离,使它们都可以独立地变化
- 结构:(左边抽象接口,右边实现接口)
- 适用于:(了解)
- 不希望在抽象和它的实现部分之间有一个固定的绑定关系。
- 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。
- 对一个抽象的实现部分的修改应对客户不产生影响,即客户代码不必重新编译。
- 有许多类要生成的类层次结构。
- 想在多个对象间共享实现,但同时要求客户并不知道这一点
- 代码展示:
public class FactoryMethod {
public static void main(String[] args) {
Product productA = new ProductA();
Color red = new Red();
productA.setName("产品A");
productA.setColor(red);
productA.Operation();
}
}
// 抽象类
abstract class Product{
private String name;
protected Color color;
public void setName(String name){
this.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());
}
}
interface Color{
public 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+"蓝色");
}
}
组合模式
- 意图:将对象组合成树型结构以表示“部分-整体”的层次结构。Composite使得用户对 单个对象 和 组合对象 的使用具有一致性
- 结构:component组合部分:AbstractFile Leaf叶节点:File Composite复合部分:Folder
- Composite定义有子组件的那些组件的行为、存储子组件、在Component接口中实现与子组件有关的操作
- Clinet通过Component接口操纵组合组件的对象
- 适用于:
- 想表示对象的部分-整体层次结构
- 希望用户忽略组合对象与单个对象的不同,用户统一地组合结构中的所有对象。
- 代码展示:
public class FactoryMethod {
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");
AbstractFile fileE = new File("fileE");
root.Add(fileB);
root.Add(folderA);
root.Add(fileE);
folderA.Add(fileC);
folderA.Add(fileD);
print(root);
}
static void print(AbstractFile file){
file.printName();
List<AbstractFile> childrenList = file.getChildrenFile();
if (childrenList == null) return; // 遇到文件返回空
for (AbstractFile child:childrenList){
print(child);
}
}
}
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> getChildrenFile();
}
class Folder extends AbstractFile{
private List<AbstractFile> childrenFile = new ArrayList<AbstractFile>();
public Folder (String name){
this.name=name;
}
@Override
public boolean Add(AbstractFile file){
childrenFile.add(file);
return true;
}
public boolean Remove(AbstractFile file){
childrenFile.remove(file);
return true;
}
public List<AbstractFile> getChildrenFile(){
return childrenFile;
}
}
class File extends AbstractFile{
public File (String name){
this.name=name;
}
@Override
public boolean Add(AbstractFile file){
return false;
}
@Override
public boolean Remove(AbstractFile file){
return false;
}
public List<AbstractFile> getChildrenFile(){
return null;
}
}
装饰器模式
- 意图:动态地给一个对象添加一些额外的职责。
- 结构:
- 适用于:
- 在不影响其他对象地情况下,以动态、透明的方式给单个对象添加职责。
- 处理那些可以撤销的职责。
- 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;另一种情况可能是,由于类定义被隐藏,或类定义不能用于生成子类。
外观模式
- 意图:为子系统中的一组接口提供一个一致的界面。
- 结构:(像是网站中包含了许多个网页界面)
- 适用于:
- 要为一个复杂子系统提供一个简单接口时。
- 客户程序与抽象类的实现部分之间存在着很大的依赖性。
- 当需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点。
享元模式
- 意图:运用共享技术有效地支持大量细粒度的对象
- 结构:
- 适用于:
- 一个应用程序使用了大量的对象
- 完全由于使用大量的对象,造成很大的存储开销
- 对象的大多数状态都可变为外部状态。(外部:易变;内部:不变)
- 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象
- 应用程序不依赖于对象标识。
- 代码展示:(五子棋)
public class FactoryMethod {
public static void main(String[] args) {
PieceFactory factory = new PieceFactory();
Piece whiiePiece = factory.getPiece(0);
whiiePiece.draw(2332,3124);
}
}
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:"+" 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:"+" x:"+x+" y"+y);
}
}
代理模式
- 意图:为其他对象提供一种代理以控制对这个对象的访问
- 结构:(代购:Poxy:代购方,保存一个引用使得代理可以访问实体…)
- 适用于:Poxy模式适用于在需要比较通用和复杂的对象指针代替简单的指针,常见情况有:
- 远程代理:为一个对象在不同地址空间提供局部代表
- 虚代理:根据需要创建开销很大的对象
- 保护代理:控制对原始对象的访问,用于对象应该有不同的访问权限的时候
- 智能引用:取代了简单的指针,它在访问对象时执行一些附加操作
- 代码展示:
public class FactoryMethod {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
Poxy poxy = new Poxy(realSubject);
poxy.Buy();
}
}
interface Subject{
public void Buy();
}
class Poxy implements Subject{
protected RealSubject realSubject;
public Poxy(RealSubject realSubject){
this.realSubject=realSubject;
}
@Override
public void Buy(){
System.out.println("办理前的手续");
realSubject.Buy();
System.out.println("办理后的进程");
}
}
class RealSubject implements Subject{
public void Buy(){
System.out.println("pay money");
}
}
行为型模式11
对类或对象怎样交互和怎样分配职责进行描述
行为型中类模式有两种:解释器和模板方法模式
责任链模式
- 意图:使多个对象都有机会处理请求,从而避免请求的发送者和接受之间的耦合关系。将这些对象连城一条线,并沿着这条链传递请求,直到有一个对象处理它为止。
- 结构:(Eg.批假条过程)
- 适用于:
- 有多个的对象可以处理一个请求,哪个对象处理该请求 运行时刻自动确定
- 想在不明确指定接收者的情况下向多个对象中的一个提交一个请求
- 可处理一个请求的对象集合应该被动态指定
命令模式
- 意图:
- 结构:(eg.电视机开关机:命令接口Command包含开机和关机,请求者Invoker遥控器,请求者Receive电视机)
- 适用于:
- 抽象出 待执行的动作 以参数化某对象
- 在不同的时刻指定、排列和执行请求
- 支持取消操作。
- 支持修改日志
- 用 构建在原语操作上的高层操作 构造一个系统
- 代码展示:
public class FactoryMethod {
public static void main(String[] args) {
Tv tv = new Tv();
Command onCommand = new OnCommand(tv);
Command offCommand = new OffCommand(tv);
Invoker invoker = new Invoker();
invoker.setCommand(onCommand); //遥控器发出开机指令
invoker.call(); //获取电视机的状态(动作)
System.out.println("========================================");
invoker.setCommand(offCommand); //遥控器发出关机指令
invoker.call(); //获取电视机的状态(动作)
}
}
class Invoker{ //请求者
private Command command; //请求者命令
public void setCommand(Command command){ // 设置 请求者的请求命令
this.command=command;
}
public void call(){
command.Execute();
}
}
interface Command{
public void Execute();
}
class OnCommand implements Command{
private Tv tv;
public OnCommand(Tv tv){
this.tv=tv;
}
public void Execute(){
tv.OnAction();
}
}
class OffCommand implements Command{
private Tv tv;
public OffCommand(Tv tv){
this.tv=tv;
}
public void Execute(){
tv.OffAction();
}
}
class Tv{
public void OnAction(){
System.out.println("电视机已开机...");
}
public void OffAction(){
System.out.println("电视机已关机...");
}
}
解释器模式
- 意图:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
- 结构:
- 适用于:当有一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象语法树时,(例如)
- 该文法简单
- 效率不是一个关键问题
迭代器模式
-
意图:提供一种方法顺序访问一个聚合对象中的各个元素,且不需要暴露该对象的内部表示
-
结构:Aggregate:定义创建相应迭代器对象的接口;ConcreteAggregate:实现创建相应迭代器的接口,该操作返回ConcreteIterator
-
适用于:
- 访问一个聚合对象的内容而无须暴露它的内部表示。
- 支持对聚合对象的多种遍历
- 为遍历不同的聚合结构提供一个统一的接口。
-
代码展示:
//在java中可创建Iterator对象
//iterator.hasNext()是否有下一个元素
//iterator.Next()取出下一个元素
中介者模式
- 意图:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
- 结构:(eg.上课递纸条,传递纸条的人——ConcreteMediator)
- 适用于:
- 一组对象以定义良好但是复杂的方式进行通信,产生的相互依赖关系结构混乱且难以理解
- 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象
- 想定制一个分布在多个类中的行为,而又不想生成太多的子类
备忘录模式
- 意图:在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态
- 结构:
- 适用性:
- 必须保存一个对象在某一时刻的(部分)状态,这样以后需要时它才能恢复到先前的状态
- 如果一个用接口来让其他对象直接得到这些状态,将会暴露对象的实现细节并破坏对象的封装性。
观察者模式
- 意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
- 结构:(eg.Bilibili关注的up主——粉丝)
- 适用于:
- *当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变时。
- 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两者封装在独立的对象中以使它们可以各自独立地改变和复用。
- *当一个对象必须通知其他对象,而它又不能假定其他对象是谁,即不希望这些对象时紧耦合的
- 代码展示:
public class FactoryMethod {
public static void main(String[] args) {
Subject subjectA = new ConcreteSubject("A");
Observe observeB = new ConcreteObserve("John",subjectA);
Observe observeC = new ConcreteObserve("Bob",subjectA);
Observe observeD = new ConcreteObserve("Anne",subjectA);
Observe observeE = new ConcreteObserve("Mike",subjectA);
subjectA.setState("已更新");
System.out.println("=================================================");
subjectA.Detach(observeE);
subjectA.setState("停更一周");
}
}
interface Subject{
public void Attach(Observe observe); //添加观察者
public void Detach(Observe observe); //删除观察者
public void Notify(); //状态改变后 通知所有观察者
public void setState(String state); //设置状态
public String getState(); //获取状态
}
class ConcreteSubject implements Subject{
private String name; //up主名
private List<Observe> observeList;
private String state;
public String getState(){
return state;
}
public void setState(String state){
this.state=state;
System.out.println(name+"的状态发生了变化,现在的状态为:"+state);
Notify();
}
public ConcreteSubject(String name){
state = "未更新";
this.name=name;
observeList = new ArrayList<Observe>();
}
@Override
public void Attach(Observe observe){
observeList.add(observe);
}
public void Detach(Observe observe){
observeList.remove(observe);
}
public void Notify(){
for (Observe observe:observeList){
observe.Update();
}
}
}
interface Observe{
public void Update();
}
class ConcreteObserve implements Observe{
private String name; //粉丝名
private String state;
private Subject subject;
public ConcreteObserve(String name,Subject subject){
this.name=name;
this.subject=subject;
subject.Attach(this);
state = subject.getState();
}
@Override
public void Update(){
System.out.println(name+"收到通知!");
state = subject.getState();
System.out.println(name+"改变后的状态:"+state); //让当前观察者状态 和 改变了之后的目标A状态保持一致
}
}
状态模式
- 意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类
- 结构:
- 适用于:
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态常用一个或多个枚举常量表示。
- 一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为。
- 代码展示:
//售卖机例子
public class FactoryMethod {
public static void main(String[] args) {
Context context = new Context(); //count=3
System.out.println(context.getState());
context.Request(); //购买一瓶饮料,count=3
context.Request(); //购买一瓶饮料,count=2
context.Request(); //购买一瓶饮料,count=1
System.out.println(context.getState());
context.Request(); //count=0
System.out.println(context.getState()); //count=5
context.Request(); //购买一瓶饮料
System.out.println(context.getCount());
}
}
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{ //有货
private Context context;
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{ //无货
private Context context;
public void Handle(Context context){
int count = context.getCount();
if (count == 0){
System.out.println("购买失败!请等待补货...");
//假如补货5瓶饮料
context.setCount(5);
System.out.println("补货成功!请重新购买!");
context.setState(new StateA());
}
}
}
策略模式
- 意图:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互依赖。此模式使得算法可以独立于使用它们的客户而变化
- 结构:
- 适用于:
- 许多相关的类仅仅是行为有异。
- 需要使用一个算法的不同变体
- 算法使用客户不应该知道的数据
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,将相关的条件分支移入它们各自的Strategy类中,以代替这些条件语句
- 代码展示:
public class FactoryMethod {
public static void main(String[] args) {
Strategy add = new AddStrategy();
Strategy subtract = new SubtractStrategy();
Strategy multiply = new MultiplyStrategy();
OperationContext context = new OperationContext(add);
context.Operation(34,99 );
}
}
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{
public void TwoNumberOperation(int a,int b){
System.out.println(a + b);
}
}
class SubtractStrategy implements Strategy{
public void TwoNumberOperation(int a,int b){
System.out.println(a - b);
}
}class MultiplyStrategy implements Strategy{
public void TwoNumberOperation(int a,int b){
System.out.println(a * b);
}
}
模板方法模式
- 意图:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤
- 结构:
- 适用于:
- 一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为应被提取出来并集中到一个公共父类,以避免代码重复。
- 控制子类扩展。
访问者模式
- 意图:表示一个作用于某对象结构中的各元素的操作。它允许在不改变各元素的类的前提下定义作用于这些元素的新操作
- 结构:
- 适用于:
- 一个对象结构包含很多类对象,它们有不同的接口,而用户想对这些对象实施一些依赖于其具体类的操作
- 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作
- 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而又想要避免这些操作“污染”这些对象的类
- 代码实现:
public class FactoryMethod {
public static void main(String[] args) {
PersonStructure structure = new PersonStructure();
Visitor1 visitor1 = new Visitor1();
System.out.println("访问者1的访问记录:");
structure.Accept(visitor1);
System.out.println("学生年龄的总和:"+visitor1.getStudentAgeSum()+",老师年龄的总和:"+visitor1.getTeacherAgeSum());
Visitor2 visitor2 =new Visitor2();
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{
private int studentAgeSum= 0;
private int teacherAgeSum= 0;
public int getStudentAgeSum() {
return studentAgeSum;
}
public int getTeacherAgeSum() {
return teacherAgeSum;
}
@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();
}
}
class Visitor2 implements Visitor{
private int maxScore = -1;
private int maxWorkYear = -1;
public int getMaxScore(){
return maxScore;
}
public int getMaxWorkYear() {
return maxWorkYear;
}
@Override
public void visitStudent(Student student) {
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.getAge());
maxWorkYear = Math.max(maxWorkYear, teacher.getWorkYear());
}
}
class PersonStructure{
private List<Person> personList = new ArrayList<Person>();
public PersonStructure(){
personList.add(new Student("Bob",20,100));
personList.add(new Student("Jane",22,140));
personList.add(new Student("Mike",18,888));
personList.add(new Teacher("Miss Liu",29,4));
personList.add(new Teacher("Miss Wu",45,10));
personList.add(new Teacher("Miss Huang",43,23));
}
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){
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public abstract void Accept(Visitor visitor);
}
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;
}
}