拿捏Java:23种设计模式

76 阅读19分钟

一、创建型

类:

工厂方法:
    定义一个用于创建对象的接口,让子类决定实例化哪一个类
    适用性:一个类不知道他所创建的对象的类的时候;
            一个类希望由其子类指定它所创建的对象的时候;
            一个工厂只能创建一类产品;

对象:

抽象工厂:
    提供一个创建一系列相关或者相互依赖对象的接口,无需指定他们具体的类;
    适用性:**一个系统独立于他的产品的创建、组合、表示;
            强调一系列相关的产品对象设计以便进行联合使用;**
            只想显示接口,而不是实现;
            一个工厂可以创建多类产品;
生成器模式:
    复杂对象的构建和表示分离,同样的构建过程可以有不同的表示;
    适用性:创建复杂对象的算法应该独立于该对象的组成部分和装配方式;
            构造过程必须允许被构造对象有不同的表示;
原型模式:
    本身是一个实例,包含clone方法;(制作简历,避免重复代码)
    用原型实例指定创建对象的种类,并且通过复制这些原型创建新对象;
    适应性:一个系统独立于他的产品的创建、构成、表示时;
            要实例化的类是在运行时指定的;
            避免创建一个与产品类层次平行的工厂类层次时;
            一个类的实例只能有几个不同状态组合中的一种时
单例模式:
   一个类只有一个实例,并提供一个访问他的全局访问点
   适用性:类只有一个实例,并且客户可以从一个众所周知的访问点访问它
            唯一实例可以通过子类化扩展,客户不需要改变代码就能使用一个扩展实例;

二、结构型

只有类适配器模式,其他都是对象

1、装饰者

适用性:不影响其他对象的前提下,动态的透明的给一个对象添加额外的职责;
        处理那些可以撤销的职责;
        当不能采用生成子类的方式进行扩充时(子类数量太多;类定义被隐藏或者类定义不能定义子类);
        

image.png

image.png

image.png

//抽象构建角色
public abstract class FastFood {
    private float price;
    private String desc;

    public FastFood(float price, String desc) {
        this.price = price;
        this.desc = desc;
    }

    public FastFood() {
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
    public abstract float cost();
}
//具体构建角色
public class FiredRice extends FastFood {
    public FiredRice(){
        super(10,"炒饭");
    }
    public float cost() {
        return getPrice();
    }
}
//具体构建角色
public class FiredNoodles extends FastFood {
    public FiredNoodles(){
        super(12,"炒面");
    }
    public float cost() {
        return getPrice();
    }
}
//抽象装饰者角色
public abstract class Garnish extends FastFood{
    //声明快餐类对象
    private FastFood fastfood;//重点在这里的聚合,让两者产生了关联

    public FastFood getFastfood() {
        return fastfood;
    }

    public void setFastfood(FastFood fastfood) {
        this.fastfood = fastfood;
    }

    public Garnish( FastFood fastfood,float price, String desc) {
        super(price, desc);
        this.fastfood = fastfood;
    }

    public Garnish(FastFood fastfood) {
        this.fastfood = fastfood;
    }
}
//具体的装饰者角色
public class Egg extends Garnish{
    public Egg(FastFood fastfood) {
        super(fastfood,1,"鸡蛋");
    }

    public float cost() {
        return getFastfood().getPrice()+getPrice();
    }

    @Override
    public String getDesc() {
        return super.getDesc()+getFastfood().getDesc();
    }
}
//具体的装饰者角色
public class Bacon extends Garnish{
    public Bacon(FastFood fastfood) {
        super(fastfood,5,"培根");
    }

    public float cost() {
        return getFastfood().getPrice() + getPrice();
    }

    @Override
    public String getDesc() {
        return super.getDesc()+getFastfood().getDesc();
    }
}
public class Client {
    public static void main(String[] args) {
        FastFood food=new FiredNoodles();
        System.out.println(food.getDesc()+" "+food.cost());
        food=new Egg(food);
        System.out.println(food.getDesc()+" "+food.cost());
        food=new Bacon(food);
        System.out.println(food.getDesc()+" "+food.cost());

    }
}

image.png

2、桥接

适用性:不希望在抽象和实现部分有固定的绑定关系;
        类的抽象和他的实现都可以通过子类的方式加以扩充;
        对抽象的实现部分的修改对客户没有影响;
        有许多类要生成的类层次结构;
        想在多个类之间共享实现;
        

image.png

image.png

image.png

//实现化角色
public interface VideoFile {
    void decode(String filename);
}
//具体的实现化角色
public class AviFile implements VideoFile {

    public void decode(String filename) {
        System.out.println("avi视频文件"+filename);
    }
}
//具体的实现化角色
public class RmvbFile implements VideoFile {
    public void decode(String filename) {
        System.out.println("Rmvb文件"+filename);
    }
}
//抽象化角色
public  abstract class OperatingSystem {
    protected VideoFile videoFile;//重点在这里的聚合

    public OperatingSystem(VideoFile videoFile) {
        this.videoFile = videoFile;
    }

    public abstract void play(String filename) ;
}
//扩展抽象化角色
public class Windows extends OperatingSystem {
    public Windows(VideoFile videoFile) {
        super(videoFile);
    }

    public void play(String filename) {
        videoFile.decode(filename);
    }
}
//扩展抽象化角色
public class Mac extends OperatingSystem {
    public Mac(VideoFile videoFile) {
        super(videoFile);
    }
    public void play(String filename) {
        videoFile.decode(filename);
    }
}
//rmvb文件:heart
public class Client {
    public static void main(String[] args) {
        RmvbFile rmvb=new RmvbFile();
        Mac mac=new Mac(rmvb);
        mac.play("heart");

    }
}

image.png

3、外观

适用性:为复杂子系统提供一个简单接口;
    客户程序和抽象类的实现之间存在很大的依赖关系;
    需要构建层次结构的子系统时,定义子系统每层的入口点;

image.png

image.png

image.png

//子系统角色
public class Light {
    public void on(){
        System.out.println("打开灯。。。。。");
    }
    public void off(){
        System.out.println("关闭灯。。。。。");
    }
}
public class AirCondition {
    public void on(){
        System.out.println("打开空调。。。。。");
    }
    public void off(){
        System.out.println("关闭空调。。。。。");
    }
}
public class TV {
    public void on(){
        System.out.println("打开电视。。。。。");
    }
    public void off(){
        System.out.println("关闭电视。。。。。");
    }
}
package com.sweet.pattern.facade;
//外观角色
public class SmartAppliancesFacate {
    //聚合灯,空调,电视
    private Light light;
    private TV tv;
    private AirCondition airCondition;

    public SmartAppliancesFacate() {
        light=new Light();
        tv=new TV();
        airCondition=new AirCondition();
    }
    public void say(String message){
        if(message.contains("open")){
            on();
        }else if(message.contains("close")){
            off();
        }else{
            System.out.println("i donnot know what you say");
        }
    }
    private void on(){
        light.on();
        tv.on();
        airCondition.on();
    }
    private void off(){
        light.off();
        tv.off();
        airCondition.off();
    }
}
public class Client {
    public static void main(String[] args) {
        SmartAppliancesFacate sm=new SmartAppliancesFacate();
        sm.say("open");

    }
}

image.png

4、组合

适用性:树形结构,部分-整体层次结构;
        想表示对象的部分-整体层次结构;
        希望用户忽略组合对象和单个对象的不同,用户将统一的使用组合结构中的所有对象;

image.png

image.png

image.png

image.png

不管是菜单(有子菜单或子菜单项),还是菜单项(最后一个层级),都应该继承自统一的接口,这个接口称为菜单组件

菜单和菜单项继承了菜单组件

菜单项聚合了菜单组件

//菜单组件
public abstract class MenuComponent {
    protected String name;
    protected int level;
    //添加子菜单
    public void add(MenuComponent menuComponent){
        throw new UnsupportedOperationException();
    }
    //删除子菜单
    public void remove(MenuComponent menuComponent){
        throw new UnsupportedOperationException();
    }
    //返回指定的菜单
    public MenuComponent getIndex(int index){
        throw new UnsupportedOperationException();
    }
    //获取本菜单或菜单项的名称
    public String getName(){
        return name;
    }
    //打印菜单名称(包括子菜单和子菜单项)
    public abstract void print();

}
//菜单
public class Menu extends MenuComponent {
    //存储子菜单或子菜单项
    protected List<MenuComponent> list=new ArrayList<MenuComponent>();

    public Menu(String name,int level){
        this.name=name;
        this.level=level;
    }
    @Override
    public void add(MenuComponent menuComponent) {
        list.add(menuComponent);
    }

    @Override
    public void remove(MenuComponent menuComponent) {
        list.remove(menuComponent);
    }

    @Override
    public MenuComponent getIndex(int index) {
        return list.get(index);
    }

    public void print() {
        for (int i = 0; i < level; i++) {
            System.out.print("--");
        }
        //打印本菜单名称
        System.out.println(name);
        //打印子菜单或子菜单项名称
        for (MenuComponent menuComponent : list) {
            menuComponent.print();
        }
    }
//菜单项
public class MenuItem extends MenuComponent {
    public MenuItem(String name,int level){
        this.name=name;
        this.level=level;
    }

    public void print() {
        for (int i = 0; i < level; i++) {
            System.out.print("--");
        }
        System.out.println(name);
    }
}
public class Client {
    public static void main(String[] args) {

        Menu menu1=new Menu("菜单管理",2);
        menu1.add(new MenuItem("页面访问",3));
        menu1.add(new MenuItem("展开菜单",3));
        menu1.add(new MenuItem("编辑菜单",3));
        menu1.add(new MenuItem("删除菜单",3));
        menu1.add(new MenuItem("新增菜单",3));
        Menu menu2=new Menu("权限设置",2);
        menu2.add(new MenuItem("页面访存",3));
        menu2.add(new MenuItem("提交保存",3));
        Menu menu3=new Menu("角色管理",2);
        menu3.add(new MenuItem("页面访问",3));
        menu3.add(new MenuItem("新增角色",3));
        menu3.add(new MenuItem("修改角色",3));
        Menu menu=new Menu("系统管理",1);
        menu.add(menu1);
        menu.add(menu2);
        menu.add(menu3);

        menu.print();
    }
}

5、享元

适用性:运用共享技术支持大量细粒度的对象;
        一个应用程序使用了大量的对象,造成了很大的开销;
        对象的大部分状态都可变成外部状态,如果删除对象的外部状态,可以用其他对象代替很多组对象;
        应用程序不依赖于对象标识。

image.png

image.png

image.png

image.png

//抽象享元角色
public abstract class AbstractBox {
    public abstract String getShape();
    public void display(String color){
        System.out.println("图形:"+getShape()+"的颜色是"+color);
    }

}
//具体享元角色
public class IBox extends AbstractBox{

    public String getShape() {
        return "I";
    }
}
public class LBox extends AbstractBox{

    public String getShape() {
        return "L";
    }
}
public class OBox extends AbstractBox{

    public String getShape() {
        return "O";
    }
}
//享元工厂角色:用单例设计模式实现
public class BoxFactory{
    private HashMap<String,AbstractBox> map;
    private BoxFactory(){
        map=new HashMap<String, AbstractBox>();
        map.put("I",new IBox());
        map.put("L",new LBox());
        map.put("O",new OBox());
    }
    //提供一个方法获取该工厂类对象
    public static BoxFactory getInstance(){
        return boxFactory;
    }
    private static BoxFactory boxFactory=new BoxFactory();

    //根据名称获取图形对象
    public AbstractBox getShap(String name){
        return map.get(name);
    }
}
public class Client {
    public static void main(String[] args) {
        AbstractBox box1 = BoxFactory.getInstance().getShap("I");
        box1.display("red");
        AbstractBox box2 = BoxFactory.getInstance().getShap("L");
        box2.display("yellow");
        AbstractBox box3 = BoxFactory.getInstance().getShap("L");
        box3.display("blue");
 }
}

image.png

6、代理

适用性:在需要比较通用和复杂的对象指针代替简单指针的时候;

image.png

image.png

image.png

public interface SellTickets {
    public void sell();
}

public class TrainStation implements SellTickets {

    public void sell() {
        System.out.println("火车站卖票");
    }
}

public class ProxyStation implements SellTickets {
    TrainStation trainStation=new TrainStation();

    public void sell() {
        System.out.println("代理商收取费用");
        trainStation.sell();
    }
}

public class Client {
    public static void main(String[] args) {
        ProxyStation proxyStation=new ProxyStation();
        proxyStation.sell();
    }
}

7、适配器模式(类适配器+对象适配器)

适用性:想创建一个可以使用的类,该类可以和其他不相关的类或者不相关的接口协同工作;
    使用一个已存在的子类,但是不可能对每一个都进行子类化以匹配接口;

image.png

image.png

image.png

image.png

类适配器

image.png image.png

image.png

//目标接口
public interface CDCard {
    public String readCDCard();
    public void writeCDCard(String msg);
}
//具体的cd卡
public class CDCardImpl implements CDCard {
    @Override
    public String readCDCard() {
        return "cdCard read msg";
    }

    @Override
    public void writeCDCard(String msg) {
        System.out.println("CDCard write msg"+msg);
    }
}
//适配者类接口
public interface TFCard {
    public String ReadTFCard();
    public void WriteTFCard(String msg);
}
//适配者类
public class TFCardImpl implements TFCard {
    @Override
    public String ReadTFCard() {
        return "TFCard read msg";
    }

    @Override
    public void WriteTFCard(String msg) {
        System.out.println("TF write msg"+msg);
    }
}
//适配器类,继承适配者类,实现目标接口
public class cdAdapterTF extends  TFCardImpl implements CDCard  {
   @Override
    public String readCDCard() {
        return "cdAdapterTF"+ReadTFCard();
    }
    @Override
    public void writeCDCard(String msg) {
        WriteTFCard("cdAdapterTF+lunwenkuaixiehaoba");
    }
}
//计算机只能读取cdcard
public class Computer {//只能读cdcard
    public String readCard(CDCard cdCard){
        if(cdCard==null){
            throw new NullPointerException("sdcard is not null");
        }
        return cdCard.readCDCard();
    }
}

public class Client {
    public static void main(String[] args) {
        Computer computer=new Computer();
        System.out.println(computer.readCard(new cdAdapterTF()));
    }
}

如果目标接口是一个类的话,这个类适配器模式是不可用的

对象适配器

image.png

其他类和接口与类适配器一致,只是sdAdapterTF内容发生变化

public class sdAdapterTF implements SDCard  {
//采用了聚合
    private TFCard tfcard;
    public sdAdapterTF(TFCard tfcard){
        this.tfcard=tfcard;
    }
    public String readSD() {
        return "TFCardImpl"+tfcard.readTF();
    }

    public void writeSD(String msg) {
        System.out.println("TFCardImpl");
        tfcard.writeTF(msg);
    }
}

三、行为型

类:解释器模式+模板方法; 其他都是对象

1、模板方法(Template Method)

适用性:一次性实现算法的不变部分,将可变部分留给子类实现;
        各个子类中的公共部分提取出来集中到一个公共父类当中,避免代码重复;
        

image.png

image.png

image.png

public abstract class AbstractClass {
    //模板方法定义
    public final void cookProcess(){
        pourOil();
        heatOil();
        pourVegetable();
        pourSauce();
        fry();
    }
    public void pourOil(){
        System.out.println("daoyou");
    }
    public void heatOil(){
        System.out.println("reyou");
    }
    public abstract void pourVegetable();
    public abstract void pourSauce();
    public void fry(){
        System.out.println("fanchao");
    }
}

public class Concrete_class_baocia extends AbstractClass {
    public void pourVegetable() {
        System.out.println("下锅的蔬菜是包菜");
    }

    public void pourSauce() {
        System.out.println("下锅的调料是辣椒");
    }
}

public class Concrete_class_Caixin extends AbstractClass {
    public void pourVegetable() {
        System.out.println("下锅的蔬菜是菜心");
    }

    public void pourSauce() {
        System.out.println("下锅的调料是蒜蓉");
    }
}

public class Client {
    public static void main(String[] args) {
        Concrete_class_baocia baocai=new Concrete_class_baocia();
        baocai.cookProcess();
    }
}

2、策略模式(Strategy Method)

意图:定义一系列算法,把他们封装起来,并且使他们之间可以相互替换;
适用性:许多相关的类仅仅是行为有异,提供了一种用多个行为中的一种行为来配置一个类的方法;
    需要使用一个算法的不同变体;
    算法使用客户不应该知道的数据;
    一个类定义了多个行为,且这些行为在这个类中以多个条件语句的形式出现,把相关的条件分支语句移入到各自的策略类中,以代替这些条件语句;

image.png

image.png

image.png

image.png

public interface Strategy {//抽象策略
    void strategy();
}
//具体策略
public class strategyA implements Strategy {
    public void strategy() {
        System.out.println("满100减50");
    }
}
public class strategyB implements Strategy {
    public void strategy() {
        System.out.println("满100减20");
    }
}
public class strategyC implements Strategy {
    public void strategy() {
        System.out.println("满100减10");
    }
}
//环境类
public class SaleMan {
    //聚合策略方法
    private Strategy stragety;

    public SaleMan(Strategy stragety) {
        this.stragety = stragety;
    }
    public void SaleManShow(){
        stragety.strategy();
    }
}
//客户类
public class Clients {
    public static void main(String[] args) {
        SaleMan saleman=new SaleMan(new strategyA());
        saleman.SaleManShow();
    }
}

image.png

3、命令模式(Command Method)

适用性:抽象出待执行的动作以参数化对象;
    在不同的时刻指定、排列、执行请求;
    支持取消操作;
    支持修改日志;
    用构建在原语操作上的高层操作构造一个系统。

image.png

image.png

image.png

public class Order {
    private int diningTable;//餐桌号
    private Map<String,Integer> foodDir=new HashMap<String, Integer>();//某菜品需要几份

    public int getDiningTable() {
        return diningTable;
    }

    public void setDiningTable(int diningTable) {
        this.diningTable = diningTable;
    }

    public Map<String, Integer> getFoodDir() {
        return foodDir;
    }

    public void setFood(String name, int num) {
        foodDir.put(name,num);
    }
}

public interface Command {
    //抽象命令类角色
    void execute();
}

public class OrderCommand implements Command {
    //具体命令角色
    //给某个厨师哪份订单
    private cheif receiver;
    private Order order;
    public OrderCommand(cheif receiver, Order order) {
        this.receiver = receiver;
        this.order = order;
    }
    public void execute() {
        System.out.println(order.getDiningTable()+"号餐桌开始制作");
        Map<String, Integer> foodDir = order.getFoodDir();
        Set<Map.Entry<String, Integer>> entries = foodDir.entrySet();
        for (Map.Entry<String, Integer> entry : entries) {
            receiver.makefood(entry.getKey(),entry.getValue());
        }
        System.out.println(order.getFoodDir()+"制作完成了");

    }
}

public class cheif {
    //实现者,接收者
    public void makefood(String foodname,int num){
        System.out.println("制作菜品"+foodname+num+"份");
    }
}

public class Waitor {
    //调用者,请求者
    private List<Command> cmds=new ArrayList<Command>();

    public void setCmd(Command cmd) {
        cmds.add(cmd);
    }
    public void OrderUp(){
        System.out.println("服务员喊:来订单了");
        for (Command command : cmds) {
            command.execute();
        }
    }
}

public class Clients {
    public static void main(String[] args) {
        //创建第一个订单对象
        Order order1=new Order();
        order1.setDiningTable(1);
        order1.setFood("xishongshi",1);
        order1.setFood("tudou",3);
        //创建第二个订单对象
        Order order2=new Order();
        order2.setDiningTable(3);
        order2.setFood("xishongshi222",2);
        order2.setFood("huanggua",1);
        //创建厨师
        cheif cheif=new cheif();
        //创建菜单命令
        OrderCommand orderCommand1=new OrderCommand(cheif,order1);
        OrderCommand orderCommand2=new OrderCommand(cheif,order2);
        //创建服务员
        Waitor waitor=new Waitor();
        waitor.setCmd(orderCommand1);
        waitor.setCmd(orderCommand2);
        waitor.OrderUp();
    }
}

image.png

4、责任链模式(Chain of Responsibility)

适用性:有多个对象可以处理该请求,具体那个对象处理在运行时刻自由决定;
    在不明确指定接收者的情况下,向多个对象中的其中一个提交请求;
    可处理一个请求的对象集合可被动态指定。

image.png

image.png

image.png

image.png

public class LeaveRequest {
    //请假申请
    private String name;
    private int num;
    private String content;
    public LeaveRequest(String name, int num, String content) {
        this.name = name;
        this.num = num;
        this.content = content;
    }
    public String getName() {
        return name;
    }
    public int getNum() {
        return num;
    }
    public String getContent() {
        return content;
    }
}
public abstract class Handler {
    //抽象处理
    static int NUM_ONE=1;
    static int NUM_THREE=3;
    static int NUM_FIVE=5;
    //某领导可以请的天数的上限和下限
    private int num_start;
    private int num_end;
    //上级领导
    private Handler nextHandler;

    public Handler(int num_start) {
        this.num_start = num_start;
    }

    public Handler(int num_start, int num_end) {
        this.num_start = num_start;
        this.num_end = num_end;
    }
    //设置上级领导对象
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }
    //提交请假条
    public void submit(LeaveRequest request){
        //该领导进行审批
        this.HandleLeave(request);
        if(this.nextHandler!=null && this.num_end<request.getNum()){
            this.nextHandler.submit(request);
        }else{
            System.out.println("审批完毕");
        }
    }
    //各级领导处理请假条的方式
    public abstract void HandleLeave(LeaveRequest request);
}
//小组长类
public class GroupHandler extends Handler{
    public GroupHandler() {
        super(0,NUM_ONE);
    }

    public void HandleLeave(LeaveRequest request) {
        System.out.println(request.getName()+"请"+request.getNum()+"天,请假理由是:"+request.getContent());
        System.out.println("小组长批准");
    }
}
//部门经理类
public class MangagerHandler extends Handler{
    public MangagerHandler() {

        super(NUM_ONE,NUM_THREE);
    }

    public void HandleLeave(LeaveRequest request) {
        System.out.println(request.getName()+"请"+request.getNum()+"天,请假理由是:"+request.getContent());
        System.out.println("部门经理批准");
    }
}
//总经理类
public class GenericManagerHandler extends Handler{
    public GenericManagerHandler()
    {
        super(NUM_THREE,NUM_FIVE);
    }

    public void HandleLeave(LeaveRequest request) {
        System.out.println(request.getName()+"请"+request.getNum()+"天,请假理由是:"+request.getContent());
        System.out.println("总经理批准");
    }
}

//客户端
public class Client {
    public static void main(String[] args) {
    //设置假条
        LeaveRequest leave=new LeaveRequest("xiaoming",2,"shengbinag");

        GroupHandler groupHandler=new GroupHandler();
        MangagerHandler mangagerHandler=new MangagerHandler();
        GenericManagerHandler genericManagerHandler=new GenericManagerHandler();
        
    //设置领导之间的关系
        groupHandler.setNextHandler(mangagerHandler);
        mangagerHandler.setNextHandler(genericManagerHandler);
    //提交请假条
        groupHandler.submit(leave);
    }
}

5、状态模式(State)

允许一个类在其内部状态改变时改变它的行为
适用性:一个对象的行为决定他的状态,并且他必须在运行时根据他的状态改变他的行为;
    有多分支条件语句,并且这些分支依赖于他的状态;

image.png

image.png

image.png

public abstract class LiftState {
    //context定义了用户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象处理
    public Context context;

    public void setContext(Context context) {
        this.context = context;
    }
    public abstract void open();
    public abstract void close();
    public abstract void run();
    public abstract void stop();
}

public class Context {
    public final static OpeningState OPENING_STATE=new OpeningState();
    public final static ClosingState CLOSING_STATE=new ClosingState();
    public final static RunningState RUNNING_STATE=new RunningState();
    public final static StoppingState STOPPING_STATE=new StoppingState();

    public LiftState liftState;
    public void setLiftState(LiftState liftState) {
        this.liftState = liftState;
    }
    public LiftState getLiftState() {
        return liftState;
    }
    public  void open(){
        this.liftState.open();
    }
    public  void close(){
        this.liftState.close();
    }
    public void run(){
        this.liftState.run();
    }
    public  void stop(){
        this.liftState.stop();
    }
}

public class OpeningState extends LiftState {
    public void open() {
        System.out.println("电梯开启了。。。。");
    }
    public void close() {
        //修改状态
        super.context.setLiftState(Context.CLOSING_STATE);
        //调用当前状态(closingState)中的close方法
        super.context.close();
    }
    public void run() {}
    public void stop() {}
}

public class RunningState extends LiftState {
    public void open() {}
    public void close() {}
    public void run() {
        System.out.println("电梯正在运行。。。。");
    }
    public void stop() {
        super.context.setLiftState(Context.STOPPING_STATE);
        super.context.stop();
    }
}

public class StoppingState extends LiftState {
    public void open() {
        super.context.setLiftState(Context.OPENING_STATE);
        super.context.open();
    }
    public void close() {}
    public void run() {
        super.context.setLiftState(Context.RUNNING_STATE);
        super.context.run();
    }
    public void stop() {
        System.out.println("电梯停止了。。。");
    }
}

public class ClosingState extends LiftState {
    public void open() {
        super.context.setLiftState(Context.OPENING_STATE);
        super.context.open();
    }
    public void close() {
        System.out.println("电梯关闭了。。。。");
    }
    public void run() {
        super.context.setLiftState(Context.RUNNING_STATE);
        super.context.run();
    }
    public void stop() {
        super.context.setLiftState(Context.STOPPING_STATE);
        super.context.stop();
    }
}

public class Client {
    public static void main(String[] args) {
        Context context=new Context();
        context.setLiftState(new RunningState());
        context.stop();
        context.open();
        context.close();
    }
}

image.png

6、观察者模式(Observer)

适用性:当对一个对象的改变同时也要改变其他对象时,且不知道待改变的对象有多少时;
    一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两方面封装在独立的对象中以使它们可以独立改变和复用;
    一个被观察对象和多个观察者对象

image.png

image.png

public interface Subject {
//抽象主题类
    //添加订阅者
    public void attach(Observer observer);
    //删除订阅者
    public void deptach(Observer observer);
    //发消息给订阅者
    public void notify(String msg);
}

public class SubscriptionSubject implements Subject {
//具体主题类(公众号)
    //聚合观察者对象
    List<Observer> weixinUser=new ArrayList<Observer>();
    public void attach(Observer observer) {
        weixinUser.add(observer);
    }

    public void deptach(Observer observer) {
        weixinUser.remove(observer);
    }

    public void notify(String msg) {
        //公众号信息发生变化时,会自动调用观察者的update方法,通知观察者
        for (Observer observer : weixinUser) {
            observer.update(msg);
        }
    }
}

public interface Observer {
//抽象观察者
    void update(String message);
}
public class weixinUser implements Observer {
//具体观察者
    String name;

    public weixinUser(String name) {
        this.name = name;
    }

    public void update(String message) {
        System.out.println(name+"收到了"+message);
    }
}

public class Client {
    public static void main(String[] args) {
        //1、创建公众号对象
        SubscriptionSubject sub=new SubscriptionSubject();
        //2、订阅公众号
        sub.attach(new weixinUser("1"));
        sub.attach(new weixinUser("2"));
        sub.attach(new weixinUser("3"));
        //3、公众号内容发生变化,通知给订阅者
        sub.notify("nihao");

    }
}

image.png

7、中介者模式(Mediator)

    适用性:一组对象以定义良好但是复杂的方式通信,产生的相互依赖关系结构混乱且难以理解;
    一个对象引用其他很多对象,并且直接与这些对象通信,导致这些对象很难复用;
    想定制一个分布在多个类中的行为,但又不想生成太多子类;
    用户对象和组对象之间不需要显示的相互引用,从而使其耦合松散,而且可以独立的改变他们之间的交互;

image.png

image.png

image.png

image.png

image.png

public abstract class Mediator {//抽象中介者角色
    public abstract void  contact(String message,Person person);
}
public abstract class Person {//抽象同事类角色
    String name;
    Mediator mediator;

    public Person(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }
}
public class MediatorConstructure extends Mediator {//具体中介者角色
    Tenate tenate;
    HouseOwner houseOwner;

    public Tenate getTenate() {
        return tenate;
    }

    public void setTenate(Tenate tenate) {
        this.tenate = tenate;
    }

    public HouseOwner getHouseOwner() {
        return houseOwner;
    }

    public void setHouseOwner(HouseOwner houseOwner) {
        this.houseOwner = houseOwner;
    }
//重点!!!
    public void contact(String message, Person person) {
        if(person==tenate){
            houseOwner.getMessage(message);
        }else{
            tenate.getMessage(message);
        }
    }
}
//具体同事类角色
public class Tenate extends Person {
    public Tenate(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);
    }
}
//具体同事类角色
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);
    }
}
//测试类
public class Client {
    public static void main(String[] args) {
        //创建中介者对象
        MediatorConstructure mediatorConstructure=new MediatorConstructure();
        //创建房主对象
        HouseOwner houseOwner=new HouseOwner("张三",mediatorConstructure);
        //创建租户对象
        Tenate tenate=new Tenate("李四",mediatorConstructure);
        //产生联系
        tenate.contact("youfangma");
        houseOwner.contact("我有一套三居室,要租吗");
    }
}

image.png

image.png

8、迭代器模式(Iterator)

适用性:访问一个聚合对象的内部而无需暴露他的内部表示;
    支持对聚合对象的多种遍历;
    为遍历一个不同结构的聚合对象提供一个统一的接口。

image.png

image.png

image.png

public class Student {
    String name;
    int num;
    public Student() {
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", num=" + num +
                '}';
    }

    public Student(String name, int num) {
        this.name = name;
        this.num = num;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

public interface StudentIterator {//抽象迭代器
    //是否有下一个对象
    boolean HasNext();
    //下一个对象是啥
    Student next();
}
public class StudentIteratorImpl implements StudentIterator {//具体迭代器
    List<Student> list;
    int position=0;
    public StudentIteratorImpl(List<Student> list) {
        this.list = list;
    }

    public boolean HasNext() {
        return position < list.size();
    }

    public Student next() {
        Student stu=list.get(position);
        position++;
        return stu;
    }
}

public interface StudentAggregate {//抽象聚合(把迭代器也联系起来了)
    void addStudent(Student student);
    void removeStudent(Student student);
    //获得学生迭代器
    StudentIterator getStudentIterator();
}

public class StudentAggregateImpl implements StudentAggregate {//具体聚合类
    List<Student> list=new ArrayList<Student>();
    public void addStudent(Student student) {
        list.add(student);
    }

    public void removeStudent(Student student) {
        list.remove(student);
    }

    public StudentIterator getStudentIterator() {

        return new StudentIteratorImpl(list);
    }
}

public class Client {
    public static void main(String[] args) {
        Student stu=new Student("zhangsan",12);
        //聚合对象
        StudentAggregate studentAggregate=new StudentAggregateImpl();
        studentAggregate.addStudent(stu);
        studentAggregate.addStudent(stu);
        studentAggregate.addStudent(stu);
        studentAggregate.addStudent(stu);
        //迭代器对象
        StudentIterator studentIterator = studentAggregate.getStudentIterator();
        while (studentIterator.HasNext()){
            Student student = studentIterator.next();
            System.out.println(student);
        }
    }
}

image.png

9、访问者模式(Visitor)

适用性:一个对象结构包含很多类对象,他们有不同的接口,而用户想对这些对象实施一些依赖于具体类的操作;
    需要对一个对象结构中的对象进行很多不同并且不相关的操作;

image.png

image.png

image.png

public interface Animal {
    void accept(Person person);
}

public class Cat implements Animal {
    public void accept(Person person) {
        person.feed(this);
        System.out.println("喂猫");
    }
}
public class Dog implements Animal {
    public void accept(Person person) {
        person.feed(this);
        System.out.println("喂狗");
    }
}

public interface Person {
    void feed(Cat cat);
    void feed(Dog dog);
}
public class Owner implements Person {
    public void feed(Cat cat) {
        System.out.println("主人喂猫");
    }

    public void feed(Dog dog) {
        System.out.println("主人喂狗");
    }
}
public class Someone implements Person {
    public void feed(Cat cat) {
        System.out.println("其他人喂猫");
    }

    public void feed(Dog dog) {
        System.out.println("其他人喂狗");
    }
}
public class Home {
    List<Animal> list=new ArrayList<Animal>();
    void addAnimal(Animal animal){
        list.add(animal);
    }
    void action(Person person){
        for (Animal animal : list) {
            animal.accept(person);
        }
    }
}

public class Client {
    public static void main(String[] args) {
        Home home=new Home();
        home.addAnimal(new Dog());
        home.addAnimal(new Dog());
        home.addAnimal(new Cat());
        home.addAnimal(new Cat());

        home.action(new Owner());
        home.action(new Someone());
    }
}

image.png

10、备忘录模式(Memento)

适用性:必须保存对象在某一时刻的状态,这样在他之后需要时可以恢复这个状态;
    如果用一个接口直接让对象得到这个状态,可能暴露对象的实现细节并破坏他的封装性;
    

image.png

image.png

image.png

image.png

public class RoleSateMemento {//备忘录
    int vit;
    int atk;
    int def;

    public RoleSateMemento(int vit, int atk, int def) {
        this.vit = vit;
        this.atk = atk;
        this.def = def;
    }
}

public class RoleStateCakerater {//备忘录管理类
    RoleSateMemento roleSateMemento;
    public RoleSateMemento getRoleSateMemento() {
        return roleSateMemento;
    }
    public void setRoleSateMemento(RoleSateMemento roleSateMemento) {
        this.roleSateMemento = roleSateMemento;
    }
}

public class GameRole {//发起人
    int vit;
    int atk;
    int def;
    public void initState(){
        vit=100;
        atk=100;
        def=100;
    }
    public int getVit() {
        return vit;
    }
    public void setVit(int vit) {
        this.vit = vit;
    }
    public int getAtk() {
        return atk;
    }
    public void setAtk(int atk) {
        this.atk = atk;
    }
    public int getDef() {
        return def;
    }
    public void setDef(int def) {
        this.def = def;
    }
    public void fight(){
        this.atk=0;
        this.def=0;
        this.vit=0;
    }
    //将现在的状态保存到备忘录里面
    public RoleSateMemento saveState(){
        return new RoleSateMemento(this.vit,this.atk,this.def);
    }
    //从备忘录里面恢复角色状态
    public void recoverRoleStateMemento(RoleSateMemento roleSateMemento){
        this.atk=roleSateMemento.atk;
        this.def=roleSateMemento.def;
        this.vit=roleSateMemento.vit;
    }
    //展示
    public void display(){
        System.out.println("生命力:"+vit);
        System.out.println("攻击力:"+atk);
        System.out.println("防御力:"+def);
    }
}

public class Client {
    public static void main(String[] args) {
        System.out.println("--------大战boss前---------");
        GameRole gameRole=new GameRole();
        gameRole.initState();
        gameRole.display();
        //保存状态
        RoleStateCakerater roleStateCakerater=new RoleStateCakerater();
        roleStateCakerater.setRoleSateMemento(gameRole.saveState());
        System.out.println("--------大战boss后---------");
        gameRole.fight();
        gameRole.display();
        System.out.println("--------恢复状态---------");
        gameRole.recoverRoleStateMemento(roleStateCakerater.getRoleSateMemento());
        gameRole.display();
    }
}

--------大战boss前---------
生命力:100
攻击力:100
防御力:100
--------大战boss后---------
生命力:0
攻击力:0
防御力:0
--------恢复状态---------
生命力:100
攻击力:100
防御力:100

11、解释器模式

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示解释语言中的句子

适应性:当有一个语言需要解释执行时,并且可将该语言中的句子表示为一个抽象语法树时。

image.png