Java开发者必备:23种设计模式全面解析
文章目录
- 一、创建型模式
- 1、工厂模式
- 简单工厂
- 工厂方法
- 2、抽象工厂模式
- 3、原型模式
- 4、建造者模式
- 5、单例模式
- 二、结构型模式
- 1、适配器模式
- 2、桥接模式
- 3、组合模式
- 4、装饰模式
- 5、外观模式
- 6、享元模式
- 7、代理模式
- 三、行为型模式
- 1、解释器模式
- 2、模板方法模式
- 3、策略模式
- 4、观察者模式
- 5、状态模式
- 6、备忘录模式
- 7、迭代器模式
- 8、命令模式
- 9、责任链模式
- 10、中介者模式
- 11、访问者模式
创建型 | 结构型 | 行为型 |
---|---|---|
工厂模式(简单工厂、工厂方法) | 适配器 Adapter | 责任链 Chain of Responsibility |
抽象工厂模式 | 桥接 Bridge | 命令 Command |
原型模式 | 组合 Composite | 解释器 Interpreter |
建造者模式 | 装饰 Decorator | 迭代器 Iterator |
单例模式 | 外观 Facade | 中介 Mediator |
享元 Flyweight | 备忘录 Memento | |
代理 Proxy | 观察者 Observer | |
状态 State | ||
策略 Strategy | ||
模板方法 Template Method | ||
访问者 Visitor |
- 创建型包含5种模式,涉及对象/对象组合的创建构建。
- 结构性包含7种模式,涉及对象/类之间的关系。
- 行为型包含11种模式,涉及对象/类的行为、状态、流程。
一、创建型模式
1、工厂模式
简单工厂
public class OperationFactory {public static Operation createOperation(char operator) {Operation operation;switch (operator) {case '+':operation = new OperationAdd();break;case '-':operation = new OperationSub();break;case '*':operation = new OperationMul();break;case '/':operation = new OperationDiv();break;default:throw new RuntimeException("unsupported operation");}return operation;}
}
public abstract class Operation {public double numberA;public double numberB;public abstract double getResult();
}
public class OperationAdd extends Operation {@Overridepublic double getResult() {return numberA + numberB;}}
public class OperationSub extends Operation {@Overridepublic double getResult() {return numberA - numberB;}}
public class OperationMul extends Operation {@Overridepublic double getResult() {return numberA * numberB;}}
public class OperationDiv extends Operation {@Overridepublic double getResult() {if (numberB == 0) {throw new RuntimeException("divided by 0");}return numberA / numberB;}}
/*** 使用工厂方法生成实例完成运算操作*/
public class Calculator {public static void main(String[] args) {Operation operation;char operator;operator = '+';operation = OperationFactory.createOperation(operator);operation.numberA = 1.2;operation.numberB = 2.3;System.out.println(operation.getResult());}
}
工厂方法
工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
/*** 工厂接口*/
public interface IFactory {Operation createOperation();
}
public class AddFactory implements IFactory {@Overridepublic Operation createOperation() {return new OperationAdd();}}
public class SubFactory implements IFactory {@Overridepublic Operation createOperation() {return new OperationSub();}}
public class MulFactory implements IFactory {@Overridepublic Operation createOperation() {return new OperationMul();}}
public class DivFactory implements IFactory {@Overridepublic Operation createOperation() {return new OperationDiv();}}
类Operation、OperationAdd、OperationSub、OperationMul、OperationDiv同上
/*** 工厂方法客户端*/
public class FactoryClient {public static void main(String[] args) {IFactory operFactory = new DivFactory();Operation operation = operFactory.createOperation();operation.numberA = 3.4;operation.numberB = 4.5;System.out.println(operation.getResult());}
}
2、抽象工厂模式
抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
// 抽象工厂
public abstract class AbstractFactory {public abstract AbstractProductA createProductA();public abstract AbstractProductB createProductB();
}
// 具体工厂1
public class ConcreteFactory1 extends AbstractFactory {@Overridepublic AbstractProductA createProductA() {return new ProductA1();}@Overridepublic AbstractProductB createProductB() {return new ProductB1();}
}
// 具体工厂2
public class ConcreteFactory2 extends AbstractFactory {@Overridepublic AbstractProductA createProductA() {return new ProductA2();}@Overridepublic AbstractProductB createProductB() {return new ProductB2();}
}
// 抽象产品A
public abstract class AbstractProductA {public abstract void methodA();
}
// 具体产品A1
public class ProductA1 extends AbstractProductA {@Overridepublic void methodA() {System.out.println("ProductA1's methodA");}
}
// 具体产品A2
public class ProductA2 extends AbstractProductA {@Overridepublic void methodA() {System.out.println("ProductA2's methodA");}
}
// 抽象产品B
public abstract class AbstractProductB {public abstract void methodB();
}
// 具体产品B1
public class ProductB1 extends AbstractProductB {@Overridepublic void methodB() {System.out.println("ProductB1's methodB");}
}
// 具体产品B2
public class ProductB2 extends AbstractProductB {@Overridepublic void methodB() {System.out.println("ProductB2's methodB");}
}
// 客户端
public class Client {public static void main(String[] args) {// 使用具体工厂1AbstractFactory factory1 = new ConcreteFactory1();AbstractProductA productA1 = factory1.createProductA();AbstractProductB productB1 = factory1.createProductB();productA1.methodA();productB1.methodB();// 使用具体工厂2AbstractFactory factory2 = new ConcreteFactory2();AbstractProductA productA2 = factory2.createProductA();AbstractProductB productB2 = factory2.createProductB();productA2.methodA();productB2.methodB();}
}
3、原型模式
原型模式,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
// 原型接口
public interface Prototype {Prototype clone();
}
// 具体原型A
public class ConcretePrototypeA implements Prototype {@Overridepublic Prototype clone() {try {return (ConcretePrototypeA) super.clone();} catch (CloneNotSupportedException e) {return null;}}
}
// 具体原型B
public class ConcretePrototypeB implements Prototype {@Overridepublic Prototype clone() {try {return (ConcretePrototypeB) super.clone();} catch (CloneNotSupportedException e) {return null;}}
}
// 客户端
public class Client {public static void main(String[] args) {// 创建具体原型A和具体原型BConcretePrototypeA prototypeA = new ConcretePrototypeA();ConcretePrototypeB prototypeB = new ConcretePrototypeB();// 克隆具体原型A和具体原型BConcretePrototypeA cloneA = (ConcretePrototypeA) prototypeA.clone();ConcretePrototypeB cloneB = (ConcretePrototypeB) prototypeB.clone();// 检查克隆是否成功System.out.println("Clone A == Prototype A: " + (cloneA!= prototypeA));System.out.println("Clone B == Prototype B: " + (cloneB!= prototypeB));}
}
4、建造者模式
建造者模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
// 产品类
public class Product {private String part1;private String part2;public void setPart1(String part1) {this.part1 = part1;}public void setPart2(String part2) {this.part2 = part2;}public void show() {System.out.println("Part 1: " + part1);System.out.println("Part 2: " + part2);}
}
// 建造者接口
public interface Builder {void buildPart();Product getResult();
}
// 具体建造者类
public class ConcreteBuilder implements Builder {private Product product = new Product();@Overridepublic void buildPart() {product.setPart1("Part 1 built by ConcreteBuilder");product.setPart2("Part 2 built by ConcreteBuilder");}@Overridepublic Product getResult() {return product;}
}
// 指挥者类
public class Director {private Builder builder;public Director(Builder builder) {this.builder = builder;}public void construct() {builder.buildPart();}
}
// 客户端
public class Client {public static void main(String[] args) {Builder builder = new ConcreteBuilder();Director director = new Director(builder);director.construct();Product product = builder.getResult();product.show();}
}
5、单例模式
单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。
/*** 线程安全的写法,单例模式最优写法*/
public class SingletonThreadSafe {private static volatile SingletonThreadSafe instance;private SingletonThreadSafe() {}public static SingletonThreadSafe getInstance() {if (instance == null) {synchronized (SingletonThreadSafe.class) {if (instance == null) {instance = new SingletonThreadSafe();}}}return instance;}
}
/*** 单例模式客户端*/
public class SingletonClient {public static void main(String[] args) {SingletonThreadSafe instance1 = SingletonThreadSafe.getInstance();SingletonThreadSafe instance2 = SingletonThreadSafe.getInstance();if (instance1.equals(instance2)) {System.out.println("同样的实例");} else {System.out.println("不同的实例");}}
}
二、结构型模式
1、适配器模式
适配器模式,将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
/*** 需要适配的类*/
public class Adaptee {public void specificRequest() {System.out.println("特殊的请求!");}}
/*** 客户所期待的接口*/
public abstract class Target {public void request() {System.out.println("普通请求!");}
}
/*** 适配器类,通过在内部包装一个Adaptee对象,把原接口转换成目标接口*/
public class Adapter extends Target {private Adaptee adaptee = new Adaptee();@Overridepublic void request() {adaptee.specificRequest();}
}
/*** 适配器客户端*/
public class AdapterClient {public static void main(String[] args) {Target target = new Adapter();target.request();}
}
2、桥接模式
桥接模式,将抽象部分与它的实现部分分离,使它们都可以独立地变化。
public abstract class Abstraction {/*** 桥接模式的关键,使得Abstraction聚合Implementor*/protected Implementor implementor;private String name;public Abstraction(String name) {this.setName(name);}public void setImplementor(Implementor implementor) {this.implementor = implementor;}public void operation() {System.out.print("Abstraction-" + this.getName() + ": ");implementor.operation();}public String getName() {return name;}public void setName(String name) {this.name = name;}
}class AbstractionA extends Abstraction {public AbstractionA(String name) {super(name);}@Overridepublic void operation() {super.operation();}}class AbstractionB extends Abstraction {public AbstractionB(String name) {super(name);}@Overridepublic void operation() {super.operation();}}
public abstract class Implementor {public abstract void operation();}class ConcreteImplemtorA extends Implementor {@Overridepublic void operation() {System.out.println("ConcreteImplemtorA的方法执行");}}class ConcreteImplemtorB extends Implementor {@Overridepublic void operation() {System.out.println("ConcreteImplemtorB的方法执行");}}
/*** 客户端*/
public class BridgeClient {public static void main(String[] args) {Abstraction a = new AbstractionA("A");a.setImplementor(new ConcreteImplemtorA());a.operation();a.setImplementor(new ConcreteImplemtorB());a.operation();Abstraction b = new AbstractionB("B");b.setImplementor(new ConcreteImplemtorA());b.operation();b.setImplementor(new ConcreteImplemtorB());b.operation();// 这样通过使用“组合/聚合复用原则”// 如果继续有AbstractionC ... 或者ConcreteImplemtorC ...// 只需要扩展类即可,不需要修改现有类,符合“开放-封闭”原则}}
3、组合模式
组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
/*** Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。*/
public abstract class Component {protected String name;public Component(String name) {this.name = name;}public abstract void add(Component component);public abstract void remove(Component component);public abstract void display(int depth);protected String repeatableLayer(int depth) {StringBuilder append = new StringBuilder();for (int i = 0; i < depth; i++) {append.append("-");}return append.toString();}}
/*** Leaf在组合中表示叶节点对象,叶节点没有子节点*/
public class Leaf extends Component {public Leaf(String name) {super(name);}@Overridepublic void add(Component component) {System.out.println("cannot add to a leaf");}@Overridepublic void remove(Component component) {System.out.println("cannot remove from a leaf");}@Overridepublic void display(int depth) {// 通过“-”的数目显示级别System.out.println(repeatableLayer(depth) + this.name);}}
/*** 定义有枝节点行为,用来存储子部件*/
public class Composite extends Component {private List<Component> children = new ArrayList<>();public Composite(String name) {super(name);}@Overridepublic void add(Component component) {children.add(component);}@Overridepublic void remove(Component component) {children.remove(component);}@Overridepublic void display(int depth) {// 显示其枝节点名称,并对其下级进行遍历System.out.println(repeatableLayer(depth) + this.name);for (Component component : children) {component.display(depth + 2);}}}
/*** 客户端。通过Component接口操作组合部件的对象*/
public class CompositeClient {public static void main(String[] args) {// 生成树根,根上长出两叶Leaf A和Leaf BComposite root = new Composite("root");root.add(new Leaf("Leaf A"));root.add(new Leaf("Leaf B"));// 根上长出分支Composite X,分支上也有两叶Leaf X-A和Leaf X-BComposite compositeX = new Composite("Composite X");compositeX.add(new Leaf("Leaf X-A"));compositeX.add(new Leaf("Leaf X-B"));root.add(compositeX);// 在Composite X上再长出分支Composite X-Y,分支上也有两叶Leaf X-Y-A和Leaf X-Y-BComposite compositeXY = new Composite("Composite X-Y");compositeXY.add(new Leaf("Leaf X-Y-A"));compositeXY.add(new Leaf("Leaf X-Y-B"));compositeX.add(compositeXY);// 显示大树的样子root.display(1);}
}
4、装饰模式
装饰模式,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
/*** Component是定义一个对象接口,可以给这些对象动态地添加职责*/
public abstract class Component {public abstract void operation();
}
/*** ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责*/
public class ConcreteComponent extends Component {@Overridepublic void operation() {System.out.println("具体对象的操作");}}
package designpattern.structural.decorator;/*** Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,* 是无需知道Decorator的存在的*/
public abstract class Decorator extends Component {protected Component component;public Component getComponent() {return component;}public void setComponent(Component component) {this.component = component;}@Overridepublic void operation() {if (component != null) {component.operation();}}}class ConcreteDecoratorA extends Decorator {private String addedState;@Overridepublic void operation() {// 首先运行原Component的operation(),再执行本类的功能,如addedState,相当于对原Component进行了装饰super.operation();addedState = "A中的new state ";System.out.println(addedState + "具体装饰对象A的操作");}
}class ConcreteDecoratorB extends Decorator {@Overridepublic void operation() {super.operation();addedBehavior();System.out.println("具体装饰对象B的操作");}public void addedBehavior() {System.out.print("B中的新增行为 ");}
}class ConcreteDecoratorC extends Decorator {@Overridepublic void operation() {super.operation();System.out.println("C没有特殊行为 " + "具体装饰对象C的操作");}}
5、外观模式
外观模式,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
/*** “系统”接口,只是标记接口,暂无任何意义*/
public interface SystemInterface {}class SubSystemOne implements SystemInterface {public void methodOne() {System.out.println("子系统方法一");}
}class SubSystemTwo implements SystemInterface {public void methodTwo() {System.out.println("子系统方法二");}
}class SubSystemThree implements SystemInterface {public void methodThree() {System.out.println("子系统方法三");}
}class SubSystemFour implements SystemInterface {public void methodFour() {System.out.println("子系统方法四");}
}
/*** 外观类,它需要了解所有的子系统的方法或属性,进行组合,以备外界调用*/
public class Facade {SubSystemOne subSystemOne;SubSystemTwo subSystemTwo;SubSystemThree subSystemThree;SubSystemFour subSystemFour;public Facade() {subSystemOne = new SubSystemOne();subSystemTwo = new SubSystemTwo();subSystemThree = new SubSystemThree();subSystemFour = new SubSystemFour();}public void methodA() {System.out.println("方法组A:");subSystemOne.methodOne();subSystemTwo.methodTwo();subSystemFour.methodFour();}public void methodB() {System.out.println("方法组B:");subSystemThree.methodThree();subSystemFour.methodFour();}
}
/*** 外观类客户端*/
public class FacadeClient {public static void main(String[] args) {// 由于Facade的作用,客户端可以根本不知道四个子系统的存在// 启发:维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,此时可以// 为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单// 的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作Facade facade = new Facade();facade.methodA();facade.methodB();}
}
6、享元模式
享元模式,运用共享技术有效地支持大量细粒度的对象。
/*** 享元工厂*/
public class FlyWeightFactory {private HashMap<String, FlyWeight> flyWeights = new HashMap<>();public FlyWeight getFlyWeight(String key) {if (!flyWeights.containsKey(key)) {flyWeights.put(key, new ConcreteFlyWeight());}return flyWeights.get(key);}}
/*** 所有具体享元类的超类,接受并作用于外部状态*/
public abstract class FlyWeight {public abstract void operation(int extrinsicState);}class ConcreteFlyWeight extends FlyWeight {@Overridepublic void operation(int extrinsicState) {System.out.println("具体FlyWeight:" + extrinsicState);}}class UnsharedConcreteFlyWeight extends FlyWeight {@Overridepublic void operation(int extrinsicState) {System.out.println("不共享的具体FlyWeight:" + extrinsicState);}}
/*** 客户端*/
public class FlyWeightClient {public static void main(String[] args) {int extrinsicState = 22;FlyWeightFactory factory = new FlyWeightFactory();FlyWeight fx = factory.getFlyWeight("X");fx.operation(--extrinsicState);FlyWeight fy = factory.getFlyWeight("Y");fy.operation(--extrinsicState);FlyWeight fz = factory.getFlyWeight("Z");fz.operation(--extrinsicState);FlyWeight uf = new UnsharedConcreteFlyWeight();uf.operation(--extrinsicState);}}
7、代理模式
代理模式,为其他对象提供一种代理以控制对这个对象的访问。
/*** 定义真实实体类与代理类共用的接口*/
public interface Subject {void request();
}
/*** 代理类*/
public class Proxy implements Subject {// 保存一个引用,使得代理可以访问真实实体Subject subject;public Proxy() {subject = new RealSubject();}@Overridepublic void request() {subject.request();}}
/*** 真实实体类*/
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("真实对象的请求");}}
三、行为型模式
1、解释器模式
解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
/*** 包含解释器之外的一些全局信息*/
public class Context {private String input;private String output;public String getInput() {return input;}public void setInput(String input) {this.input = input;}public String getOutput() {return output;}public void setOutput(String output) {this.output = output;}}
/*** 声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享*/
public abstract class AbstractExpression {public abstract void interpret(Context context);}
/*** 实现与文法中的终结符相关联的解释操作,文法中每一个终结符都有一个具体终结表达式与之相对应*/
public class TerminalExpression extends AbstractExpression {@Overridepublic void interpret(Context context) {System.out.println("终端解释器");}}
/*** 非终结符表达式,为文法中的非终结符实现解释操作。对文法中每一条规则R1、R2 ... ... Rn都需要一个具体的非终结符表达式类。*/
public class NonTerminalExpression extends AbstractExpression {@Overridepublic void interpret(Context context) {System.out.println("非终端解释器");}}
/*** 构建表示该文法定义的语言中一个特定的句子的抽象语法树,调用解释操作*/
public class InterpreterClient {public static void main(String[] args) {Context context = new Context();List<AbstractExpression> list = new ArrayList<>();list.add(new TerminalExpression());list.add(new NonTerminalExpression());list.add(new TerminalExpression());list.add(new TerminalExpression());for (AbstractExpression expression : list) {expression.interpret(context);}}}
2、模板方法模式
模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
/*** 模板方法抽象类:不变的部分给出具体实现,变化的部分封装为抽象方法延迟到子类实现*/
public abstract class AbstractTemplate {public abstract void primitiveOperation1();public abstract void primitiveOperation2();public void templateMethod() {primitiveOperation1();primitiveOperation2();System.out.println("模板方法结束\n");}
}
/*** 具体类A*/
public class ConcreteClassA extends AbstractTemplate {@Overridepublic void primitiveOperation1() {System.out.println("具体类A的方法1实现");}@Overridepublic void primitiveOperation2() {System.out.println("具体类A的方法2实现");}
}
/*** 具体类B*/
public class ConcreteClassB extends AbstractTemplate {@Overridepublic void primitiveOperation1() {System.out.println("具体类B的方法1实现");}@Overridepublic void primitiveOperation2() {System.out.println("具体类B的方法2实现");}
}
/*** 模板方法客户端*/
public class TemplateClient {public static void main(String[] args) {AbstractTemplate abstractTemplate;abstractTemplate = new ConcreteClassA();abstractTemplate.templateMethod();abstractTemplate = new ConcreteClassB();abstractTemplate.templateMethod();}
}
3、策略模式
场景:商场促销。简单工厂模式虽然也能解决这个问题,但这个模式只是解决对象的创建问题,而且由于工厂本身包括了所有的收费方式,商场是可能经常性地更改打折额度和返利额度,每次维护或扩展收费方式都要改动这个工厂。所以它不是最好的办法。
面对算法的时常变动,应该有更好的办法。
策略模式:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
/*** 上下文*/
public class Context {Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}/*** 上下文接口*/public void contextInterface() {strategy.algorithmInterface();}
}
/*** 策略接口*/
public interface Strategy {void algorithmInterface();
}class ConcreteStrategyA implements Strategy {@Overridepublic void algorithmInterface() {System.out.println("策略A的具体算法实现");}
}class ConcreteStrategyB implements Strategy {@Overridepublic void algorithmInterface() {System.out.println("策略B的具体算法实现");}
}class ConcreteStrategyC implements Strategy {@Overridepublic void algorithmInterface() {System.out.println("策略C的具体算法实现");}
}
package designpattern.behavioral.strategy;/*** 客户端使用策略*/
public class StrategyClient {public static void main(String[] args) {Context context;context = new Context(new ConcreteStrategyA());context.contextInterface();context = new Context(new ConcreteStrategyB());context.contextInterface();context = new Context(new ConcreteStrategyC());context.contextInterface();}
}
4、观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
/*** 主题或抽象通知者*/
public abstract class Subject {private List<Observer> observers = new ArrayList<>();public void attach(Observer observer) {observers.add(observer);}public void detach(Observer observer) {observers.remove(observer);}public void notifyObserver() {for (Observer observer : observers) {observer.update();}}
}
/*** 具体主题或通知者*/
public class ConcreteSubject extends Subject {private String subjectState;public String getSubjectState() {return subjectState;}public void setSubjectState(String subjectState) {this.subjectState = subjectState;}
}
/*** 抽象观察者*/
public abstract class Observer {public abstract void update();
}
/*** 具体观察者*/
public class ConcreteObserver extends Observer {private String name;private String observerState;private ConcreteSubject concreteSubject;public ConcreteObserver(ConcreteSubject concreteSubject, String name) {this.setName(name);this.setConcreteSubject(concreteSubject);}@Overridepublic void update() {this.setObserverState(concreteSubject.getSubjectState());System.out.println("观察者" + this.getName() + "的新状态是" + this.getObserverState());}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getObserverState() {return observerState;}public void setObserverState(String observerState) {this.observerState = observerState;}public ConcreteSubject getConcreteSubject() {return concreteSubject;}public void setConcreteSubject(ConcreteSubject concreteSubject) {this.concreteSubject = concreteSubject;}
}
/*** 观察者模式客户端代码*/
public class ObserverClient {public static void main(String[] args) {ConcreteSubject concreteSubject = new ConcreteSubject();concreteSubject.attach(new ConcreteObserver(concreteSubject, "X"));concreteSubject.attach(new ConcreteObserver(concreteSubject, "Y"));concreteSubject.attach(new ConcreteObserver(concreteSubject, "Z"));concreteSubject.setSubjectState("ABC");concreteSubject.notifyObserver();}
}
5、状态模式
状态模式,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
/*** Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态*/
public class Context {private State state;public Context(State state) {this.state = state;}public State getState() {return state;}public void setState(State state) {this.state = state;}public void request() {this.state.handle(this);}
}
/*** 抽象状态类*/
public abstract class State {public abstract void handle(Context context);
}class ConcreteStateA extends State {@Overridepublic void handle(Context context) {System.out.println("现在是在状态A");context.setState(new ConcreteStateB());}
}class ConcreteStateB extends State {@Overridepublic void handle(Context context) {System.out.println("现在是在状态B");context.setState(new ConcreteStateC());}
}class ConcreteStateC extends State {@Overridepublic void handle(Context context) {System.out.println("现在是在状态C");context.setState(new ConcreteStateA());}
}
/*** 客户端:不断请求,不断更改状态*/
public class StateClient {public static void main(String[] args) {Context context = new Context(new ConcreteStateA());context.request();context.request();context.request();context.request();context.request();}
}
6、备忘录模式
备忘录:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
/*** 发起人(Originator) 类*/
public class Originator {private String state;public Memento createMemento() {return new Memento(this.state);}public void recoverMemento(Memento memento) {this.setState(memento.getState());}public void show() {System.out.println("state = " + this.state);}public String getState() {return state;}public void setState(String state) {this.state = state;}
}
/*** 备忘录(Memento)类*/
public class Memento {private String state;public Memento(String state) {this.state = state;}public String getState() {return state;}public void setState(String state) {this.state = state;}
}
/*** 管理者(CareTaker)类:管理备忘录*/
public class CareTaker {private Memento memento;public Memento getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}
}
/*** 客户端*/
public class MementoClient {public static void main(String[] args) {// 设置初始状态Originator originator = new Originator();originator.setState("On");originator.show();// 管理者通过备忘录保存状态,由于有了很好地封装,可以隐藏Originator的实现细节CareTaker careTaker = new CareTaker();careTaker.setMemento(originator.createMemento());// 改变状态originator.setState("Off");originator.show();// 通过管理者从备忘录中恢复状态originator.recoverMemento(careTaker.getMemento());originator.show();}
}
7、迭代器模式
迭代器模式,提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
/*** 聚集接口** @param <T>*/
public interface Aggregate<T> {Iterator<T> createIterator();
}
/*** 具体聚集类** @param <T>*/
public class ConcreteAggregate<T> implements Aggregate<T> {private List<T> items = new ArrayList<>();@Overridepublic Iterator<T> createIterator() {return new ConcreteIterator<T>(this);}public int count() {return items.size();}public T getItems(int index) {return items.get(index);}public void setItems(T item) {items.add(item);}
}
/*** 迭代器接口** @param <T>*/
public interface Iterator<T> {T first();T next();boolean isDone();T currentItem();
}
/*** 具体迭代器类,给出一种具体迭代的实现方式。思考:迭代器表示的是一种迭代的行为,而聚集则是真正要被迭代的数据集合。* 之所以要将迭代器和聚集分开,就是为了将行为与数据分开。 可类比Java中Iterator与Iterable的关系进行理解** @param <T>*/
public class ConcreteIterator<T> implements Iterator<T> {private ConcreteAggregate<T> concreteAggregate;private int current = 0;public ConcreteIterator(ConcreteAggregate<T> concreteAggregate) {this.setConcreteAggregate(concreteAggregate);}@Overridepublic T first() {return concreteAggregate.getItems(0);}@Overridepublic T next() {current++;if (current < concreteAggregate.count()) {return concreteAggregate.getItems(current);}return null;}@Overridepublic boolean isDone() {return current >= concreteAggregate.count() ? true : false;}@Overridepublic T currentItem() {return concreteAggregate.getItems(current);}public ConcreteAggregate<T> getConcreteAggregate() {return concreteAggregate;}public void setConcreteAggregate(ConcreteAggregate<T> concreteAggregate) {this.concreteAggregate = concreteAggregate;}public int getCurrent() {return current;}public void setCurrent(int current) {this.current = current;}
}
/*** 迭代器客户端*/
public class IteratorClient {public static void main(String[] args) {ConcreteAggregate<String> bus = new ConcreteAggregate<String>();bus.setItems("大鸟");bus.setItems("小菜");bus.setItems("行李");bus.setItems("老外");bus.setItems("公交内部员工");bus.setItems("小偷");Iterator<String> iterator = new ConcreteIterator<>(bus);while (!iterator.isDone()) {System.out.println(iterator.currentItem() + "请买票!");iterator.next();}}
}
8、命令模式
命令模式,将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以 及支持可撤销的操作。
/*** 用来声明执行操作的接口*/
public abstract class Command {protected List<Reciever> recievers;public Command(List<Reciever> recievers) {this.recievers = recievers;}public void addRecievers(Reciever reciever) {this.recievers.add(reciever);}public abstract void execute();}// 将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现execute
class ConcreteCommand extends Command {public ConcreteCommand(List<Reciever> recievers) {super(recievers);}@Overridepublic void execute() {for (Reciever reciever : recievers) {reciever.action();}}
}
/*** 知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者。真正执行请求的地方!*/
interface Reciever {void action();
}class RecieverA implements Reciever {@Overridepublic void action() {System.out.println("RecieverA执行请求!");}}class RecieverB implements Reciever {@Overridepublic void action() {System.out.println("RecieverB执行请求!");}
}class RecieverC implements Reciever {@Overridepublic void action() {System.out.println("RecieverC执行请求!");}
}
/*** 要求该命令执行这个请求*/
public class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void executeCommand() {command.execute();}
}
/*** 创建一个具体命令对象并设定它的接收者*/
public class CommandClient {public static void main(String[] args) {List<Reciever> recievers = new ArrayList<>();recievers.add(new RecieverA());recievers.add(new RecieverB());recievers.add(new RecieverC());Command command = new ConcreteCommand(recievers);Invoker invoker = new Invoker();invoker.setCommand(command);invoker.executeCommand();}
}
9、责任链模式
责任链模式,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
/*** 处理请求的接口*/
public abstract class Handler {protected Handler successor;public void setSuccessor(Handler successor) {this.successor = successor;}public abstract void handleRequest(int request);
}/*** 具体处理者类,处理它所负责的请求,可访问它的后继者,如果可处理该请求,则处理,否则转给它的后继者处理*/
class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(int request) {if (request >= 0 && request <= 10) {System.out.println(this.getClass().getName() + "处理了请求" + request);} else if (successor != null) {successor.handleRequest(request);}}}class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(int request) {if (request > 10 && request <= 20) {System.out.println(this.getClass().getName() + "处理了请求" + request);} else if (successor != null) {successor.handleRequest(request);}}}class ConcreteHandlerC extends Handler {@Overridepublic void handleRequest(int request) {if (request > 20 && request <= 30) {System.out.println(this.getClass().getName() + "处理了请求" + request);} else if (successor != null) {successor.handleRequest(request);}}
}
/*** 向链上的具体处理者对象提交请求*/
public class Client {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();Handler handlerC = new ConcreteHandlerC();handlerA.setSuccessor(handlerB);handlerB.setSuccessor(handlerC);int[] requests = {2, 14, 5, 6, 8, 23, 12, 21};for (int i : requests) {handlerA.handleRequest(i);}}
}
10、中介者模式
中介者模式,用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
/*** 抽象同事类*/
public abstract class Colleague {protected Mediator mediator;public Colleague(Mediator mediator) {this.mediator = mediator;}public abstract void sendMsg(String message);public abstract void notifyMsg(String message);}class ConcreteColleague1 extends Colleague {public ConcreteColleague1(Mediator mediator) {super(mediator);}@Overridepublic void sendMsg(String message) {mediator.send(message, this);}@Overridepublic void notifyMsg(String message) {System.out.println("同事1得到消息:" + message);}}class ConcreteColleague2 extends Colleague {public ConcreteColleague2(Mediator mediator) {super(mediator);}@Overridepublic void sendMsg(String message) {mediator.send(message, this);}@Overridepublic void notifyMsg(String message) {System.out.println("同事2得到消息:" + message);}
}
/*** 抽象中介者类*/
public abstract class Mediator {public abstract void send(String message, Colleague colleague);}class ConcreteMediator extends Mediator {// 需要了解所有的具体同事对象private ConcreteColleague1 c1;private ConcreteColleague2 c2;public ConcreteColleague1 getC1() {return c1;}public void setC1(ConcreteColleague1 c1) {this.c1 = c1;}public ConcreteColleague2 getC2() {return c2;}public void setC2(ConcreteColleague2 c2) {this.c2 = c2;}@Overridepublic void send(String message, Colleague colleague) {// 重写发送信息的方法,根据对象做出选择判断,通知对象if (colleague == c1) {c2.notifyMsg(message);} else {c1.notifyMsg(message);}}
}
/*** 客户端*/
public class MediatorClient {public static void main(String[] args) {ConcreteMediator concreteMediator = new ConcreteMediator();// 让两个具体同事类认识中介者对象ConcreteColleague1 concreteColleague1 = new ConcreteColleague1(concreteMediator);ConcreteColleague2 concreteColleague2 = new ConcreteColleague2(concreteMediator);// 让中介者认识各个具体同事类对象concreteMediator.setC1(concreteColleague1);concreteMediator.setC2(concreteColleague2);// 具体同事类对象的消息发送都是通过中介者对象转发concreteColleague1.sendMsg("吃过饭了没有?");concreteColleague2.sendMsg("没有呢,你打算请客?");}
}
11、访问者模式
访问者模式,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
/*** 为该对象结构中ConcreteElement的每一个类声明一个Visit操作*/
public abstract class Visitor {public abstract void visitConcreteElementA(ConcreteElementA concreteElementA);public abstract void visitConcreteElementB(ConcreteElementB concreteElementB);}class ConcreteVisitor1 extends Visitor {@Overridepublic void visitConcreteElementA(ConcreteElementA concreteElementA) {System.out.println(concreteElementA.getClass().getSimpleName() + "被"+ this.getClass().getSimpleName() + "访问");}@Overridepublic void visitConcreteElementB(ConcreteElementB concreteElementB) {System.out.println(concreteElementB.getClass().getSimpleName() + "被"+ this.getClass().getSimpleName() + "访问");}
}class ConcreteVisitor2 extends Visitor {@Overridepublic void visitConcreteElementA(ConcreteElementA concreteElementA) {System.out.println(concreteElementA.getClass().getSimpleName() + "被"+ this.getClass().getSimpleName() + "访问");}@Overridepublic void visitConcreteElementB(ConcreteElementB concreteElementB) {System.out.println(concreteElementB.getClass().getSimpleName() + "被"+ this.getClass().getSimpleName() + "访问");}
}
/*** 定义一个accept操作,它以一个访问者为参数*/
public abstract class Element {public abstract void accept(Visitor visitor);
}class ConcreteElementA extends Element {@Overridepublic void accept(Visitor visitor) {visitor.visitConcreteElementA(this);}
}class ConcreteElementB extends Element {@Overridepublic void accept(Visitor visitor) {visitor.visitConcreteElementB(this);}
}
/*** 提供一个高层的接口以允许访问者访问它的元素*/
public class ObjectStructure {private List<Element> elements = new ArrayList<>();public void attach(Element element) {elements.add(element);}public void detach(Element element) {elements.remove(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}
/*** 客户端*/
public class VisitorClient {public static void main(String[] args) {ObjectStructure o = new ObjectStructure();o.attach(new ConcreteElementA());o.attach(new ConcreteElementB());ConcreteVisitor1 visitor1 = new ConcreteVisitor1();ConcreteVisitor2 visitor2 = new ConcreteVisitor2();o.accept(visitor1);o.accept(visitor2);}
}
提示:更多内容可以访问Clang’s Blog:https://www.clang.asia
相关文章:

Java开发者必备:23种设计模式全面解析
文章目录 一、创建型模式1、工厂模式简单工厂工厂方法 2、抽象工厂模式3、原型模式4、建造者模式5、单例模式 二、结构型模式1、适配器模式2、桥接模式3、组合模式4、装饰模式5、外观模式6、享元模式7、代理模式 三、行为型模式1、解释器模式2、模板方法模式3、策略模式4、观察…...

编译OpenWrt步骤
实验平台搭建 硬件平台:hilink-7628n核心板 宿主机系统:ubuntu20.04 server 宿主机安装所需工具: binutils bzip2 diff find flex gawk gcc-6 getopt grep install libc-dev libz-dev make4.1 perl python3.7 rsync subversion unzip whi…...

Linux:confluence8.5.9的部署(下载+安装+pojie)离线部署全流程 遇到的问题
原文地址Linux:confluence8.5.9的部署(下载安装破ji)离线部署全流程_atlassian-agent-v1.3.1.zip-CSDN博客 背景:个人使用2核4g 内存扛不住 总是卡住,但是流程通了所以 直接公司开服务器干生产 个人是centos7 公司…...

✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
api.js //封装ajax方法 import $g from "../sg";//vue项目使用 import $ from jquery;//(提示:原生开发页面请前往https://jquery.com下载最新版jQuery) import { Message } from "element-ui";//element项目使用 // import axios from "…...

axios 请求跨域问题
文章目录 1. 使用场景2. 解决办法 1. 使用场景 ① 编写后端测试接口,Vue-CLI 的默认端口为 8080,所以为避免端口冲突,我们后端的端口号换成 8081。 ② 前端通过 axios 向后端服务发起请求。 <script> import axios from axios export…...

什么是 Faiss?
好的,我来详细解释 Faiss,它的用途、使用场景,以及如何安装和使用。 什么是 Faiss? Faiss 是由 Facebook AI Research 开发的一个开源库,专门用于高效的相似性搜索和聚类。它非常擅长在高维向量空间中进行快速搜索&a…...

24.UE5枚举,怪物分类,龙卷风技能
2-26 枚举、怪物分类、龙旋风技能、掉落概率_哔哩哔哩_bilibili 目录 1.枚举 1.1枚举类型的创建 1.2 将枚举类型绑定到怪物蓝图上 1.3枚举类型的使用 1.3.1创建新的掉落物 1.3.2更改怪物掉落逻辑 2.龙卷风技能 2.1输入映射 2.2龙卷风发射物的创建 2.3龙卷风伤害逻辑…...

什麼是ISP提供的公共IP地址?
公共IP地址是ISP分配給設備或網路的全球唯一地址。此地址允許通過互聯網識別和訪問設備。ISP提供的公共IP地址具有幾個關鍵特徵: 1.每個公網IP在全球網路內都是唯一的,避免衝突。 2. 公共 IP 地址對其他網路可見,並且可用於地理定位設備。 …...

git操作总结
git基本知识 工作区域 远程仓库: 就是我们托管在github或者其他代码托管平台上的仓库。本地仓库: 就是在我们本地通过git init命令初始化的新建的仓库。工作区: 就是我们写代码、编辑文件的地方。暂存区: 当工作区的内容写好了之…...

CompressAI安装!!!
我就不说废话了,直接给教程,还是非常简单的 但是我看了好多帖子,都没有说明情况 一定要看最后最后的那个注释 正片开始: 一共有三种方式: 第一种就是本机安装: 在网址上下载对应版本Links for compre…...

豆包MarsCode算法题:最小周长巧克力板组合
问题描述 思路分析 这道题可以抽象为一个最优化问题: 问题分析 每个正方形的面积为 k ,对应的边长为 k ,周长为 4k 。给定整数 n ,我们需要找到若干正方形,使得它们的面积之和恰好等于 n: 同时尽量最小…...

vue项目添加骨架屏vue-skeleton-webpack-plugin,通过app.vue添加骨架屏,解决衔接空白问题
安装插件 yarn add vue-skeleton-webpack-plugin在 webpack 中引入插件:以4版本为例配置如下 vue.config.js plugins: [new SkeletonWebpackPlugin({webpackConfig: {entry: {app: path.join(__dirname, ./src/components/entry-skeleton.js),},},minimize: true,…...

测试实项中的偶必现难测bug之模糊匹配逻辑
问题: 现在有一个场景,如果只是通过功能测试会比较难测,例如刚开始我们做会员的时候,只有白银会员,在用户分群的场景下,需要用条件逻辑匹配,当时开发用了like的匹配方式没有问题。1年后加了白银试用会员,导致在统计会员分群的时候明明条件选的是白银会员,但是统计的数…...

Vue:后端返回二进制文件,前端如何实现浏览器自动下载?
Vue项目开发中,遇到界面下载功能时,前端如何实现将后端返回二进制文件在浏览器自动下载? 一、关键代码: export function downloadFile(fileName) {axios({method: post,url: process.env.VUE_APP_BASE_API /cgi-bin/file,data:…...

Android解压zip文件到指定目录
很多时候需要把一个预制的zip文件解压到根目录,下面是一个实例代码: private static final int BUFFER_SIZE 4096;public static void unZip(String zipFilePath, String targetDir) throws IOException {File destDir new File(targetDir);if (!destD…...

主要用于图像的颜色提取、替换以及区域修改
这段代码涉及了以下几个关键步骤,主要用于图像的颜色提取、替换以及区域修改。下面是对代码的详细解析: 1. 导入库 import cv2 import matplotlib.pyplot as plt import numpy as npcv2: OpenCV库,用于图像处理。matplotlib.pyplot: 用于绘…...

gbase8c之运维操作
导出结构: gs_dump -U gbase8s -W Password123 -f /tmp/dump_only_structure.sql -p 15400 sids_station -n public -s -F p 导出数据: gs_dump -U gbase8s -W Password123 -f /tmp/dump_only_data.sql -p 15400 sids_station -n public -a -F p 导入…...

云原生学习
1、云原生学习 文章目录 1、云原生学习1. 介绍2. Docker容器化 1. 介绍 什么是云原生?原生指使用JAVA等语言编写的项目,云是指将项目部署到云服务器上云平台:公有云、私有云 本地平台是指直接部署在自己计算机,而开发的应用一定要…...

深入解析 Vue 3 中的 defineExpose
深入解析 Vue 3 中的 defineExpose 在 Vue 3 的组合式 API(Composition API)中,defineExpose 是一个重要的辅助函数,专门用于在 <script setup> 模式下暴露组件内部的属性和方法给父组件使用。本文将详细解析 defineExpose…...

Docker3:docker基础1
欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…...
【UGUI】背包的交互01(道具信息跟随鼠标+道具信息面板显示)
详细程序逻辑过程 初始化物品栏: 在 Awake 方法中,通过标签找到提示框和信息面板。 循环生成10个背包格子,并为每个格子设置图标和名称。 为每个格子添加 UInterMaager232 脚本,以便处理交互事件。 关闭提示框和信息面板&#…...

ubuntu20.04中编译安装gcc 9.2.0
ubuntu20.04中编译安装gcc 9.2.0,步骤如下: #install compile dependence libraries 1:$ sudo apt install libgmp-dev libisl-dev libmpc-dev libmpfr-dev # install gcc 9.2.0 # download source code 2:$ wget http://ftp.gnu.org/gn…...

ss 命令的基本用法
ss 命令的基本用法 ss [选项]-tanl 选项解释 -t:显示 TCP 连接。-a:显示所有连接(包括监听端口)。-n:显示数字形式的地址和端口号,而不是解析为主机名和服务名。-l:仅显示监听的端口。 使用示…...

Leetcode198. 打家劫舍(HOT100)
代码: class Solution { public:int rob(vector<int>& nums) {int n nums.size();vector<int> f(n 1), g(n 1);for (int i 1; i < n; i) {f[i] g[i - 1] nums[i - 1];g[i] max(f[i - 1], g[i - 1]);}return max(f[n], g[n]);} }; 这种求…...

kafka基础
文章目录 一、Kafka入门1.1、JMS1.2、生产者-消费者模式1.3、ZooKeeper 二、kafka基础架构2.1、producer2.2、kafka cluster2.2.1、broker2.2.2、Controller2.2.3、Topic2.2.4、Partition2.2.5、Replication2.2.6、Leader & Follower 2.3、consumer 一、Kafka入门 Kafka是一…...

STM32CUBEIDE FreeRTOS操作教程(九):eventgroup事件标志组
STM32CUBEIDE FreeRTOS操作教程(九):eventgroup事件标志组 STM32CUBE开发环境集成了STM32 HAL库进行FreeRTOS配置和开发的组件,不需要用户自己进行FreeRTOS的移植。这里介绍最简化的用户操作类应用教程。以STM32F401RCT6开发板为…...

Python设计模式详解之2 —— 工厂模式
工厂模式(Factory Pattern)是一种创建型设计模式,旨在定义一个用于创建对象的接口,但由子类决定实例化哪个类。工厂模式可以帮助我们将对象的创建与其使用分离,增强代码的可扩展性和维护性。 工厂模式的分类 简单工厂…...

【Zookeeper】二、主从应用(master-worker架构)
以一张具有代表性的架构风格展开本篇论述 一般在这种架构中,主节点所负责的工作主要有 跟踪从节点状态分配任务到从节点,并跟踪任务的有效性(任务是否正常执行完成) 此时,我们需要关注三个问题 主节点崩溃 如果主节…...

Diffusion【2】:VAE
系列文章目录 文章目录 系列文章目录前言1. Abstract2. Introduction2.1. Motivation2.2. Contribution 3. Methods3.1. Problem Scenario3.2. The variational bound3.3. The SGVB estimator and AEVB algorithm3.3.1. Stochastic Gradient Variational Bayes Estimator3.3.2.…...

高级java每日一道面试题-2024年11月19日-基本篇-获取一个类Class对象的方式有哪些?
如果有遗漏,评论区告诉我进行补充 面试官: 获取一个类Class对象的方式有哪些? 我回答: 在 Java 中,获取一个类的 Class 对象有多种方式。这些方式各有优缺点,适用于不同的场景。以下是常见的几种方法及其详细解释: 1. 使用 new 关键字实…...