五种创建型设计模式
- 单例模式(Singleton Pattern)
- 原型模式(Prototype Pattern)
- 工厂方法模式(Factory Method Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 建造者模式(Builder Pattern)
七种结构型设计模式
- 代理模式(Proxy Pattern)
- 适配器模式(Adapter Pattern)
- 桥接模式(Bridge Pattern)
- 装饰模式(Decorator Pattern)
- 门店模式(Facade Pattern)
- 享元模式(Flyweight Pattern)
- 组合模式(Composite Pattern)
十一种行为型设计模式
- 模板方法模式(Template Method Pattern)
- 策略模式(Strategy Pattern)
- 命令模式(Command Pattern)
- 责任链模式(Chain of Responsibility Pattern)
- 状态模式(State Pattern)
- 观察者模式(Observer Pattern)
- 中介者模式(Mediator Pattern)
- 迭代器模式(Iterator Pattern)
- 访问者模式(Visitor Pattern)
- 备忘录模式(Memento Pattern)
- 解释器模式(Interpreter Pattern)
单例模式
确保一个类只有一个实例,并提供一个全局访问点。
- 饿汉式:线程安全,调用效率高,但不能延迟加载(static修饰在类初始化时就已经开始实例化了)
- 懒汉式:线程安全,调用效率不高,但能延迟加载(方法同步,效率低)
- 双重校验:线程安全,调用效率高,可延迟加载
- 静态内部类:线程安全,调用效率高,可以延时加载
- 枚举类:枚举元素本身就是单例
/**
* @author minhy
* 饿汉式--线程安全,调用效率高,但不能延迟加载(static修饰在类初始化时就已经开始实例化了)
* @date 2023-12-07 21:33
*/
public class SingletonDemoCopy1 {
private static SingletonDemoCopy1 instance=new SingletonDemoCopy1();
private SingletonDemoCopy1(){};
private static SingletonDemoCopy1 getInstance(){
return instance;
}
}
/**
* @author minhy
* 懒汉式--线程安全,调用效率不高,可以实现延迟加载
* @date 2023-12-07 21:39
*/
public class SingletonDemoCopy2 {
private static SingletonDemoCopy2 instance=null;
private SingletonDemoCopy2(){};
//方法同步,效率低
private static synchronized SingletonDemoCopy2 getInstance(){
if (instance == null){
instance=new SingletonDemoCopy2();
}
return instance;
}
}
/**
* @author minhy
* 双重验证--线程安全,调用效率高,可以延迟加载
* @date 2023-12-08 15:56
*/
public class SingletonDemoCopy3 {
private volatile static SingletonDemoCopy3 instance;
private SingletonDemoCopy3(){};
private static SingletonDemoCopy3 getInstance(){
if (instance==null){
synchronized (SingletonDemoCopy3.class){
if (instance==null){
instance=new SingletonDemoCopy3();
}
}
}
return instance;
}
}
/**
* @author minhy
* 静态内部类--线程安全,调用效率高,可以延时加载
* @date 2023-12-08 17:00
*/
public class SingletonDemoCopy4 {
private static class DemoCopy4 {
private static final SingletonDemoCopy4 instance = new SingletonDemoCopy4();
}
private SingletonDemoCopy4(){};
private static SingletonDemoCopy4 getInstance(){
return DemoCopy4.instance;
}
}
/**
* @author minhy
* 枚举类
* @date 2023-12-08 17:06
*/
public enum SingletonDemoCopy5 {
//枚举元素本身就是单例
INSTANCE;
public void doSomeing(){
System.out.println("实例");
}
}
class test{
public static void main(String[] args) {
SingletonDemoCopy5 s1=SingletonDemoCopy5.INSTANCE;
SingletonDemoCopy5 s2=SingletonDemoCopy5.INSTANCE;
System.out.println(s1==s2); //true 说明是同一个实例
}
}
原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。也就是
说,这种不通过new关键字来产生一个对象,而是通过对象复制(Java中的clone或反序
列化)来实现的模式,就叫做原型模式。
/**
* @author minhy
* 原型模式--通过clone方法创建的Prototype对象不会执行构造方法
* @date 2023-12-08 17:35
*/
public class PrototypeDemo implements Cloneable{
private PrototypeDemo(){
System.out.println("执行原型模式构造器");
}
@Override
protected PrototypeDemo clone(){
try {
return (PrototypeDemo)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
PrototypeDemo prototypeDemo=new PrototypeDemo(); //执行原型模式构造器
/** 执行clone方法创建的Prototype对象 */
PrototypeDemo prototypeDemo1=prototypeDemo.clone();//不执行构造器
}
}
注意:克隆实例里面的引用对象类型是共享空间的,如果需要区分开需要深拷贝。
工厂方法模式
定义了一个创建对象的接口(类或接口中的方法),但由子类决定要实例化的类
是哪一个。工厂方法把实例化推迟到子类
public abstract class PizzaStoreV2 {
//抽象一个创建披萨的抽象方法,具体实现由各自子类去实现制作披萨的逻辑
protected abstract Pizza createPizza(String pizzaType);
public Pizza orderPizza(String pizzaType) {
Pizza pizza = createPizza(pizzaType);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
public class NYPizzaStore extends PizzaStoreV2 {
//按照披萨的类型,纽约门店的披萨子类去实现纽约制作披萨的逻辑
protected Pizza createPizza(String pizzaType) {
Pizza pizza = null;
if (pizzaType.equals("cheese")) {
pizza = new NYCheesePizza();
} else if (pizzaType.equals("pepperoni")) {
pizza = new NYPepperoniPizza();
} else if (pizzaType.equals("clam")) {
pizza = new NYClamPizza();
} else if (pizzaType.equals("veggie")) {
pizza = new NYVeggiePizza();
}
return pizza;
}
/**
* 工厂方法
*/
private static void pizzaStoreV2Test() {
PizzaStoreV2 pizzaStore = new NYPizzaStore(); // 选择纽约地区的披萨店
pizzaStore.orderPizza("cheese");
}
抽象工厂模式
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
public class NYPizzaStore extends PizzaStoreV3 {
//在工厂方法的基础上,抽像接口在创建披萨的接口子类实现上再创建一个原料工厂
protected Pizza createPizza(String pizzaType) {
Pizza pizza = null;
PizzaIngredientFactory pizzaIngredientFactory = new NYPizzaingredientFactory();
if (pizzaType.equals("cheese")) {
pizza = new CheesePizza(pizzaIngredientFactory);
} else if (pizzaType.equals("pepperoni")) {
pizza = new PepperoniPizza(pizzaIngredientFactory);
} else if (pizzaType.equals("clam")) {
pizza = new ClamPizza(pizzaIngredientFactory);
} else if (pizzaType.equals("veggie")) {
pizza = new VeggiePizza(pizzaIngredientFactory);
}
return pizza;
}
}
**
* @description 披萨原料抽象工厂
**/
public interface PizzaIngredientFactory {
Dough createDough();
Sauce createSauce();
Cheese createCheese();
Clams createClams();
}
/**
* @description 纽约原料工厂
**/
public class NYPizzaingredientFactory implements PizzaIngredientFactory {
public Dough createDough() {
return new ThickCrustDough();
}
public Sauce createSauce() {
return new PlumTomatoSauce();
}
public Cheese createCheese() {
return new MozzarellaCheese();
}
public Clams createClams() {
return new FrozenClams();
}
}
/**
* 抽象工厂
*/
private static void pizzaStoreV3Test() {
PizzaStoreV3 pizzaStore = new NYPizzaStore();
pizzaStore.orderPizza("cheese");
}
建造者模式
将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最
后构建成该复杂对象。可以封装一个产品的构造过程,并允许按步骤构造产品。
优点:
- 将一个复杂对象的创建过程封装起来。
- 允许对象通过多个步骤来创建,并且可以改变过程。
- 向客户隐藏产品内部的表现。
- 产品的实现可以被替换,因为客户只看到一个抽象接口
缺点:
- 经常被用来创建组合结构。
- 与工厂模式相比,采用生成器模式创建对象的客户,需要具备更多的领域知识
注:建造者模式其实本质上就是使用内部方法去setValue()
public interface Builder {
// 安装引擎
Builder initalEngine(String engine);
// 安装齿轮
Builder initalGear(String gear);
// 安装车门
Builder initalDoor(String door);
// 安装轮胎
Builder initailWheel(String wheel);
// 获得构建后的汽车
Car getCar();
}
public class AudiBuilder implements Builder {
private Car car;
public AudiBuilder() {
car = new Car("Audi普通的发动机",
"Audi普通标准的齿轮",
"Audi普通标准的车门",
"Audi普通标准的轮胎");
}
@Override
public Builder initalEngine(String engine) {
car.setEngine(engine);
return this;
}
@Override
public Builder initalGear(String gear) {
car.setGear(gear);
return this;
}
@Override
public Builder initalDoor(String door) {
car.setDoor(door);
return this;
}
@Override
public Builder initailWheel(String wheel) {
car.setWheel(wheel);
return this;
}
@Override
public Car getCar() {
return car;
}
}
Car createA4LCar() {
return new AudiBuilder().initalEngine("Audi的4缸发动机").initalGear("6速双离合变速箱").initalDoor("A4L的门").getCar();
}
代理模式
为某对象提供一种代理以控制对该对象的访问。即:客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
解决问题:当我们想要对一个业务类进行某些横切性的增强时,例如:增加请求与响应的日志、增加权限校验、增加远程请求对象封装等等。我们可以采用代理模式去实现,而不需要修改原有的类。
定义:代理模式为另一个对象提供一个替身或占位符,以控制对这个对象的访问。使用代理模式创建代理对象,让代理对象控制某对象的访问,被代理的对象可以是远程的对象、创建开销大的对象或需要安全控制的对象。SpringAOP中采用的JDK动态代理,就是最典型的例子。
//原请求对象接口
public interface Subject {
void request();
}
//原请求对象接口实现
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("-----RealSubject 开始执行业务操作-----");
}
}
//代理对象
public class Proxy implements Subject {
// 被代理的对象
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
@Override
public void request() {
beforeProcessor();
subject.request();
afterProcessor();
}
private void beforeProcessor() {
System.out.println("-----Proxy before processor-----");
}
private void afterProcessor() {
System.out.println("-----Proxy after processor-----");
}
}
public class ProxyTest {
public static void main(String[] args) {
// Subject subject = new RealSubject(); //-----RealSubject 开始执行业务操作-----
Subject subject = new Proxy(new RealSubject());//-----Proxy before processor-----
subject.request(); //-----RealSubject 开始执行业务操作-----
//-----Proxy after processor-----
}
}
适配器模式
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
/**
* @description 待适配类,无法正常的符合Target接入标准的类
**/
public class Adaptee {
public void prepare1() {
System.out.println("Adaptee prepare1()");
}
public void prepare2() {
System.out.println("Adaptee prepare2()");
}
public void prepare3() {
System.out.println("Adaptee prepare3()");
}
public void doingSomething() {
System.out.println("Adaptee doingSomething()");
}
}
/**
* @description 正常的符合Target接入标准的类
**/
public class NormalTarget implements Target {
public void prepare() {
System.out.println("NormalTarget prepare()");
}
public void execute() {
System.out.println("NormalTarget execute()");
}
}
/**
* @description 适配器
**/
public class Adapter implements Target {
// 待适配的类
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
//以下按照业务逻辑对待适配的类进行适配成正常的接口处理
public void prepare() {
adaptee.prepare1();
adaptee.prepare2();
adaptee.prepare3();
}
public void execute() {
adaptee.doingSomething();
}
}
桥接模式
将抽象部分和实现部分,分离解耦,使得两者可以独立地变化。桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立变化。
/**
* 抽象画笔类
*/
@Data
public abstract class BrushPenAbstraction {
// 颜色接口(Has-A关系,桥接)
protected ColorImplementor color;
// 绘画操作
public abstract void draw();
}
/**
* 颜色大类
*/
public interface ColorImplementor {
String getColor();
}
/**
* 粗毛笔实现类
*/
//继承抽象画笔类
public class BigBurshPen extends BrushPenAbstraction {
@Override
public void draw() {
System.out.println("Big and " + color.getColor() + " drawing!");
}
}
/**
* 桥梁模式测试类
*/
public class BridgeTest {
public static void main(String[] args) {
BrushPenAbstraction brushPen = new BigBurshPen();
brushPen.setColor(new RedColor());
brushPen.draw();
brushPen.setColor(new BlueColor());
brushPen.draw();
//Big and Red drawing!
//Big and Blue drawing!
}
}
装饰模式
动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更弹性的替代方案。
即:增加其额外的功能
/**
* @description 食物抽象类
**/
public abstract class Food {
String description = "食物";
public String getDescription() {
return description;
}
public abstract double cost();
}
/**
* @description 辅料抽象类
**/
public abstract class AccessoriesDecorator extends Food {
public abstract String getDescription();
}
/**
* @description 香肠
**/
public class Sausage extends AccessoriesDecorator {
private Food food;
public Sausage(Food food) {
this.food = food;
}
public String getDescription() {
return "香肠";
}
public double cost() {
System.out.println("添加香肠售价:" + 3 + "元");
return 3 + food.cost();
}
}
/**
* @description 基础版煎饼果子
**/
public class JianBing extends Food {
public JianBing() {
description = "基础版煎饼果子";
}
public double cost() {
System.out.println("基础版煎饼果子售价:" + 7 + "元");
return 7;
}
}
public class DecoratorTest {
public static void main(String[] args) {
// 创建煎饼果子
Food jianBing = new JianBing();
// 创建香肠,加入到煎饼果子中
Food sausage = new Sausage(egg);
System.out.println("总金额为:" + sausage.cost() + "元");
//添加香肠售价:3元
//基础版煎饼果子售价:7元
//总金额为:10.0元
}
}
门店模式
提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
public class ClientTest {
public static void main(String[] args) {
Car car = new Car();
car.start(); // 启动汽车,用户并不知道引擎、车门、钥匙、中控的运作
}
}
public class Car {
private Engine engine;
private Door door;
private DashboardDisplay display;
private Key key;
public Car() {
engine = new Engine();
door = new Door();
display = new DashboardDisplay();
key = new Key();
}
/** 汽车启动 */
public void start() {
if (key.turns()) {
door.lock();
engine.start();
display.refreshDisplay();
}
}
}
享元/蝇量模式
享元模式是池技术的重要实现方式,其定义如下:使用共享对象可以有效地支持大量的细粒度的对象
/**
* 蝇量模式测试类
*/
public class FlyweightTest {
private static NucleicInfoClient client = new NucleicInfoClient();
public static void main(String[] args) {
PersonInfo bob = new PersonInfo("bob", "北京市海淀区xx大街xx小区x号楼x号", 2);
PersonInfo muse = new PersonInfo("muse", "北京市朝阳区yy大街yy小区y号楼y号", 7);
PersonInfo john = new PersonInfo("john", "上海市市徐汇区zz大街zz小区z号楼z号", 4);
printPersonInfo(bob);
printPersonInfo(muse);
printPersonInfo(john);
}
public static void printPersonInfo(PersonInfo personInfo) {
NucleicInfo nucleicInfo = client.getNucleicInfo(personInfo.getNucleicId());
System.out.println(String.format("姓名=%s 居住地址=%s 核酸网点=%s", personInfo.getName(), personInfo.getAddress(),
nucleicInfo.getName()));
}
}
/**
* 核酸医院和网点信息客户端类
*/
public class NucleicInfoClient {
// 存储核酸医院和网点的pool
private HashMap<Integer, NucleicInfo> pool = Maps.newHashMap();
// 构造函数中初始化池中数据
public NucleicInfoClient() {
NucleicInfo nucleicInfo;
for (int i = 1; i <=10; i++) {
nucleicInfo = new NucleicInfo(i, "北京市第"+i+"医院核酸网点");
pool.put(nucleicInfo.getId(), nucleicInfo);
}
}
public NucleicInfo getNucleicInfo(Integer key) {
if (key == null || !pool.containsKey(key)) {
return null;
}
return pool.get(key);
}
}
/**
* 核酸医院和网点信息信息
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class NucleicInfo {
// 唯一标识
private Integer id;
// 核酸医院网点名称
private String name;
}
组合模式
允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合
/**
* 职员类
*/
@AllArgsConstructor
public abstract class AbstractCorp {
// 职员姓名
private String name = "";
// 职员的职位
private String position = "";
// 职员的薪水
private int salary = 0;
// 获得职员信息
public String getCorpInfo() {
return String.format("姓名:%s 职位:%s 薪水:%d", name, position, salary);
}
}
/**
* 管理层员工(即:非叶子节点职员)
*/
public class BranchCorp extends AbstractCorp {
private ArrayList<AbstractCorp> corps = Lists.newArrayList();
public BranchCorp(String name, String position, int salary) {
super(name, position, salary);
}
// 添加职员
public void addSubCorp(AbstractCorp... corp) {
corps.addAll(Arrays.asList(corp));
}
// 返回手下的职员
public ArrayList<AbstractCorp> getSubCorp() {
return corps;
}
}
/**
* 基层员工(即:叶子节点职员)
*/
public class LeafCorp extends AbstractCorp {
public LeafCorp(String name, String position, int salary) {
super(name, position, salary);
}
}
public class CompositeTest {
public static void main(String[] args) {
// 创建公司所有职员
BranchCorp a = new BranchCorp("A", "董事长", 100000);
BranchCorp b = new BranchCorp("B", "技术总监", 70000);
BranchCorp c = new BranchCorp("C", "人事总监", 60000);
BranchCorp d = new BranchCorp("D", "财务总监", 50000);
LeafCorp b1 = new LeafCorp("B1", "程序员", 30000);
LeafCorp b2 = new LeafCorp("B2", "程序员", 20000);
LeafCorp c1 = new LeafCorp("C1", "HR", 15000);
LeafCorp d1 = new LeafCorp("D1", "会计", 13000);
// 根据下属关系,构建树形结构
a.addSubCorp(b, c, d);
b.addSubCorp(b1, b2);
c.addSubCorp(c1);
d.addSubCorp(d1);
// 获得下属信息
System.out.println("-----a的下属-----");
getSubCorp(a);
System.out.println("-----b的下属-----");
getSubCorp(b);
}
// 获得branchCorp的下属
private static void getSubCorp(BranchCorp branchCorp) {
for (AbstractCorp corp : branchCorp.getSubCorp()) {
System.out.println("corp = " + corp.getCorpInfo());
if (corp instanceof BranchCorp) {
getSubCorp((BranchCorp) corp);
}
}
}
}
模板方法
在一个方法中定义一个算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
/**
* @description 饮品制作类
**/
public abstract class MakeBeverage {
// 准备食谱(防止子类覆盖这个方法)
final void prepareRecipe() {
/** 第一步:把水煮沸 */
boilWater();
/** 第二步:酿造饮品 */
brew();
/** 第三步:把饮品倒入杯子中 */
pourInCup();
/** 第四步:往饮品中增加调味品 */
addCondiments();
}
// 酿造
abstract void brew();
// 往饮品中增加调味品
abstract void addCondiments();
protected void boilWater() {
System.out.println("把水煮沸");
}
private void pourInCup() {
System.out.println("把饮品倒入杯子中");
}
}
/**
* @description
**/
public class Tea extends MakeBeverage {
@Override
protected void brew() {
System.out.println("用沸水浸泡茶叶");
}
@Override
protected void addCondiments() {
System.out.println("往茶叶中添加柠檬");
}
}
public class TemplateTest {
public static void main(String[] args) {
System.out.println("-----------开始冲泡茶叶-----------");
Tea tea = new Tea();
tea.prepareRecipe();
}
}
策略模式
定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
命令模式
将“请求”封装成命令对象,以便使用不同的请求、队列或日志来参数化其他对象
责任链模式
把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合
/**
* 责任链模式测试类
*/
public class ChainTest {
// 初始化待处理邮件
private static List<Email> emails = Lists.newArrayList(new Email(EmailType.FANS_EMAIL.type, "我是粉丝A"),
new Email(EmailType.COOPERATE_EMAIL.type, "我要找你们合作"),
new Email(EmailType.GARBAGE_EMAIL.type, "我是垃圾邮件"),
new Email(EmailType.FANS_EMAIL.type, "我是粉丝B"));
public static void main(String[] args) {
// 初始化处理类
AbstractProcessor ceoProcessor = new CeoProcessor();
AbstractProcessor lawProcessor = new LawProcessor();
AbstractProcessor businessProcessor = new BusinessProcessor();
AbstractProcessor garbageProcessor = new GarbageProcessor();
// 设置责任链条
ceoProcessor.setNextProcessor(lawProcessor);
lawProcessor.setNextProcessor(businessProcessor);
businessProcessor.setNextProcessor(garbageProcessor);
// 开始处理邮件
ceoProcessor.handleMessage(emails);
}
}
状态模式
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
不再使用if—else判断,而将每个状态看成一个类去操作
/**
* 例如没有投放钱币状态类
*/
public class NoQuarterState implements State {
private GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("投入钱币成功!");
gumballMachine.setState(gumballMachine.getHasQuarterState()); // 投入钱币后状态流转到下一个状态
}
@Override
public void ejectQuarter() {
System.out.println("你还没有投入钱币,不能退回钱币!");
}
@Override
public void turnCrank() {
System.out.println("你还没有投入钱币,不能扭转曲柄!");
}
@Override
public void dispense() {
System.out.println("你还没有投入钱币,糖果不可以发放!");
}
}
/**
* 状态接口类
*/
public interface State {
// 投入硬币操作
void insertQuarter();
// 退出硬币操作
void ejectQuarter();
// 扭转曲柄操作
void turnCrank();
// 发放糖果操作
void dispense();
}
观察者模式
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
/**
* @description 观察者1
**/
public class ConcreteObserver1 implements Observer {
public void update() {
System.out.println("ConcreteObserver1");
}
}
/**
* @description 观察者2
**/
public class ConcreteObserver2 implements Observer {
public void update() {
System.out.println("ConcreteObserver2");
}
}
/**
* @description 主题
**/
public class ConcreteSubject implements Subject {
private List<Observer> observers;
public ConcreteSubject() {
this.observers = new ArrayList<>();
}
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObserver() {
observers.forEach(observer -> observer.update());
}
}
/**
* @description
* @author: muse
**/
public class OberverTest {
public static void main(String[] args) {
Observer cObserver1 = new ConcreteObserver1();
Observer cObserver2 = new ConcreteObserver2();
Observer cObserver3 = new ConcreteObserver3();
/** 创建主题 */
ConcreteSubject subject = new ConcreteSubject();
/** 注册三个监听者*/
subject.registerObserver(cObserver1);
subject.registerObserver(cObserver2);
subject.registerObserver(cObserver3);
/** 发送通知 */
System.out.println("----------给cObserver1、cObserver2、cObserver3发通知----------");
subject.notifyObserver();
/** 移除一个监听者ConcreteObserver2*/
subject.removeObserver(cObserver2);
System.out.println("----------给cObserver1、cObserver3发通知----------");
subject.notifyObserver();
}
}
中介者模式
使用中介者模式来集中相关对象之间复杂的沟通和控制方式。
/**
* 中介者/调停者
*/
public class Mediator {
protected Purchase purchase;
protected Sale sale;
protected Stock stock;
public Mediator() {
purchase = new Purchase(this);
sale = new Sale(this);
stock = new Stock(this);
}
/** 采购电脑 */
public void purchaseByComputer(int num) {
int saleStatus = sale.getSaleStatus();
// 如果销售情况不好(即:没有超过80台),则采购总数减半
String msg = "";
if (saleStatus <= 80) {
num = num / 2;
msg = "由于销售不佳,采购总数减半,";
}
System.out.println(msg + "原有库存电脑" + stock.getStockNumber() + "台,现采购电脑" + num + "台");
stock.increaseComputer(num);
}
/** 销售电脑 */
public void saleSellComputer(int num) {
// 如果库存数量不足,则采购2倍的num电脑数,暂时只售卖库存中有的数量
int stockNum;
if ((stockNum = stock.getStockNumber()) < num) {
purchase.buyComputer(2*num);
num = stockNum;
}
stock.decreaseComputer(num);
}
/** 折价销售电脑 */
public void saleOffSale() {
System.out.println("折价销售电脑");
}
/** 清理库存 */
public void stockClear() {
sale.offSale(); // 折价销售电脑
purchase.refuseBuyComputer(); // 不要采购电脑
}
}
/**
* 库存功能
*/
public class Stock extends AbstractColleague {
private static int COMPUTER_NUM = 100;
public Stock(Mediator mediator) {
super(mediator);
}
/** 增加库存 */
public void increaseComputer(int number) {
COMPUTER_NUM += number;
System.out.println("电脑的库存数量为:" + COMPUTER_NUM);
}
/** 减少库存 */
public void decreaseComputer(int number) {
COMPUTER_NUM -= number;
System.out.println("电脑的库存数量为:" + COMPUTER_NUM);
}
/** 获得当前库存 */
public int getStockNumber() {
return COMPUTER_NUM;
}
/** 清理库存 */
public void clearStock() {
System.out.println("清理库存数量为:" + COMPUTER_NUM);
super.mediator.stockClear();
}
}
//交由中介去进行传达命令到具体的类处理
public class MediatorTest {
public static void main(String[] args) {
Mediator mediator = new Mediator();
System.out.println("--------采购人员采购电脑--------");
Purchase purchase = new Purchase(mediator);
purchase.buyComputer(100);
System.out.println("--------销售人员销售电脑--------");
Sale sale = new Sale(mediator);
sale.sellComputer(1);
System.out.println("--------库房人员清库处理--------");
Stock stock = new Stock(mediator);
stock.clearStock();
}
}
迭代器模式
提供一个方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
/**
* @description 我们自定义的迭代器
**/
public interface MenuIterator {
// 容器中是否还有元素
boolean hasNext();
// 获得容器中的下一个元素
MenuItem next();
}
/**
* @description 菜单项
**/
public class MenuItem {
// 菜名
private String name;
// 菜品详细介绍
private String desc;
// 是否是素食
private boolean vegetarian;
// 菜的价格
private double price;
public MenuItem(String name, String desc, boolean vegetarian, double price) {
this.name = name;
this.desc = desc;
this.vegetarian = vegetarian;
this.price = price;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
public boolean isVegetarian() {
return vegetarian;
}
public double getPrice() {
return price;
}
}
/**
* @description A餐厅的菜单(采用ArrayList存储)
**/
public class ARestaurantMenu implements Menu {
private ArrayList<MenuItem> menuItems;
public ARestaurantMenu() {
menuItems = new ArrayList<>();
addItem("油条", "油条的描述", true, 0.5);
addItem("豆浆", "豆浆的描述", true, 1.9);
addItem("茶叶蛋", "茶叶蛋的描述", true, 1.5);
addItem("小笼包", "小笼包的描述", true, 2.1);
}
private void addItem(String name, String desc, boolean vegetarian, double price) {
MenuItem menuItem = new MenuItem(name, desc, vegetarian, price);
menuItems.add(menuItem);
}
public ArrayList<MenuItem> getMenuItems() {
return menuItems;
}
@Override
public MenuIterator iterator() {
return new ARestaurantMenuIterator(menuItems);
}
}
/**
* @description
**/
public class ARestaurantMenuIterator implements MenuIterator {
private ArrayList<MenuItem> menuItems;
private Iterator<MenuItem> iterator;
public ARestaurantMenuIterator(ArrayList<MenuItem> menuItems) {
this.menuItems = menuItems;
iterator = menuItems.iterator();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public MenuItem next() {
return iterator.next();
}
}
访问者模式
表示一个作用于某个对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
/**
* @description 访问者接口
**/
public interface Visitor {
// 访问者CPU价格
void visitorCpu(Cpu cpu);
// 访问者内存价格
void visitorMemory(Memory memory);
// 获得总价
int price();
// 访问者名称
String visiterName();
}
对应的人员分类去实现这个接口,例如个人开户,公司客户等
/**
* @description 个人用户(不打折)
**/
public class PersonVisitor implements Visitor {
// 总售价
public int totalPrice;
@Override
public void visitorCpu(Cpu cpu) {
totalPrice += cpu.price();
}
@Override
public void visitorMemory(Memory memory) {
totalPrice += memory.price();
}
@Override
public int price() {
return totalPrice;
}
@Override
public String visiterName() {
return "个人用户";
}
}
/**
* @description 学生用户(有学生计划活动,打少量折扣)
**/
public class StudentVisitor implements Visitor {
// 总售价
public int totalPrice;
@Override
public void visitorCpu(Cpu cpu) {
totalPrice += cpu.price() * 0.8;
}
@Override
public void visitorMemory(Memory memory) {
totalPrice += memory.price() * 0.9;
}
@Override
public int price() {
return totalPrice;
}
@Override
public String visiterName() {
return "学生用户";
}
}
public class VisitorTest {
public static void main(String[] args) {
Computer computer = new Computer();
Visitor personVisitor = new PersonVisitor();
Visitor studentVisitor = new StudentVisitor();
Visitor companyVisitor = new CompanyVisitor();
computer.buildComputer(personVisitor);
System.out.println(String.format("针对%s,每台电脑售价为:%s元", personVisitor.visiterName(), personVisitor.price()));
computer.buildComputer(studentVisitor);
System.out.println(String.format("针对%s,每台电脑售价为:%s元", studentVisitor.visiterName(), studentVisitor.price()));
computer.buildComputer(companyVisitor);
System.out.println(String.format("针对%s,每台电脑售价为:%s元", companyVisitor.visiterName(), companyVisitor.price()));
}
}
备忘录模式
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以将该对象恢复到原先保存的状态。当你需要让对象返回之前的状态时(例如:你的用户请求“撤销”),就使用备忘录模式。
/**
* @description 文档类
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Document {
// 文档的内容
private String content;
public void print() {
System.out.println("content=" + content);
}
}
/**
* @description 备忘录
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Memento {
// 文档内容
public String content;
}
/**
* @description 备忘录管理类
*/
public class MementoManager {
// 记录备忘录信息
private Stack<Memento> mementoStack = new Stack<>();//使用堆栈保存
// 保存备忘录
public void save(Document document) {
Memento memento = new Memento(document.getContent());
mementoStack.add(memento);
}
// 撤销操作ctrl+z
public Document cancel() {
Memento memento = mementoStack.pop();//去除堆栈顶部元素
Document document = new Document();
document.setContent(memento.getContent());
return document;
}
}