Java高级开发必备-设计模式

Java高级开发必备-设计模式

观察者模式

定义了对象之间的一对多的依赖,这样一来,当一个对象改变时,它的所有的依赖者都会收到通知并自动更新。

服务接口,所有服务实现此接口

public interface Subject {

    void registerObserver(Observer observer);

    void removeObserver(Observer observer);

    void notifyObservers();

}

所有观察者需要实现此接口

public interface Observer {

    void update(String msg);

}

服务的实现类

public class SubjectForOne implements Subject {

    private ArrayList<Observer> observers = new ArrayList<>();
    private String msg;

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        int index = observers.indexOf(observer);
        if (index >= 0) {
            observers.remove(index);
        }
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(msg);
        }
    }

    /**
     * 主题更新信息
     *
     * @param msg
     */
    public void setMsg(String msg) {
        this.msg = msg;
        notifyObservers();
    }
}

模拟第一个使用者

public class ObserverUser1 implements Observer {

    public ObserverUser1(Subject subject) {
        subject.registerObserver(this);
    }

    @Override
    public void update(String msg) {
        System.out.println("-----ObserverUser1: " + msg + "");
    }
}

测试

public class Test {

    public static void main(String[] args) {
        // 创建服务号
        SubjectForOne subject = new SubjectForOne();

        // 创建两个订阅者
        ObserverUser1 user1 = new ObserverUser1(subject);
        ObserverUser2 user2 = new ObserverUser2(subject);

        subject.setMsg("3D号为:127");
        subject.setMsg("3D号为:000");
    }

}

工厂模式

  • 静态工厂模式
    项目中的辅助类,TextUtil.isEmpty等,类+静态方法。

  • 简单工厂模式
    通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

  • 工厂方法模式
    定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式把类实例化的过程推迟到子类。

  • 抽象工厂模式
    提供一个接口,用于创建相关的或依赖对象的家族,而不需要明确指定具体类。

接口工厂

public interface Factory {

    Worker work();

    Machine start();

}

各工厂实现工厂接口

public class AFactory implements Factory {
    @Override
    public Worker work() {
        return new AWorker();
    }

    @Override
    public Machine start() {
        return new AMachine();
    }
}
public class Worker {

    public String msg = "I am worker.";

}
public class AWorker extends Worker {

    public AWorker() {
        this.msg = "I am worker A.";
    }
    
}
public class Main {

    public void start(Factory factory) {
        Worker worker = factory.work();
        //Machine machine = factory.start();
        System.out.println("worker: " + worker.msg + ", machine: " + machine.msg);
    }

    public void pack() {
        System.out.println("packing");
    }

}

单例设计模式

单例模式主要是为了避免因为创建了多个实例造成资源的浪费,且多个实例由于多次调用容易导致结果出现错误,而使用单例模式能够保证整个应用中有且只有一个实例。

  • 饿汉

    public class SingletonEHan {
    
        private SingletonEHan() {}
    
        private static SingletonEHan singletonEHan = new SingletonEHan();
    
        public static SingletonEHan getInstance() {
            return singletonEHan;
        }
    }
    
  • 懒汉-双重校验锁

    public class SingletonLanhan {
    
        private SingletonLanhan() {
        }
    
        private static SingletonLanhan instance;
    
        private static SingletonLanhan getInstance() {
            if (instance == null) {
                synchronized (SingletonLanhan.class) {
                    if (instance == null) {
                        instance = new SingletonLanhan();
                    }
                }
            }
            return instance;
        }
    
    }
    
  • 内部类

    public class SingletonIn {
    
        private SingletonIn() {
        }
    
        private static class SingletonInHodler {
            private static SingletonIn singletonIn = new SingletonIn();
        }
    
        public static SingletonIn getSingletonIn() {
            return SingletonInHodler.singletonIn;
        }
    }
    
  • 枚举

    public enum SingletonEnum {
    
        instance;
    
        private SingletonEnum() {
    
        }
    
        public void method() {
            System.out.println("method");
        }
    
    }
    
    // SingletonEnum.instance.method();
    
    public enum SingtonEnum {
    
        USERS;
    
        private Users users;
    
        private SingtonEnum() {
            users = new Users(1);
        }
    
        public Users get() {
            return users;
        }
    }
    
    // SingtonEnum.USERS.get()
    

适配器模式

将一个类的接口转换成客户期望的另一个接口,适配器让原本接口不兼容的类可以相互合作。这个定义还好,说适配器的功能就是把一个接口转成另一个接口。

提供5V电压的接口

public interface V5Power {

    int v5();

}

一部手机

public class Mobile {

    public void inputPower(V5Power power) {
        int p = power.v5();
        System.out.println("我需要的是5V电压充电,现在是" + p + "V");
    }

}

200V电

public class V20Power {

    public int v200() {
        System.out.println("我提供200V电源");
        return 200;
    }

}

适配器,完成200V转5V

public class V5PowerAdapter implements V5Power {

    private int v200;

    public V5PowerAdapter(V20Power power) {
        this.v200 = power.v200();
    }

    @Override
    public int v5() {
        System.out.println("适配器: 经过复杂的操作,将" + v200 + "v电压转为5v");
        return 5;
    }
}
public class Test {

    public static void main(String[] args) {
        Mobile mobile = new Mobile();
        V5Power v5 = new V5PowerAdapter(new V20Power());
        mobile.inputPower(v5);
    }

}

装饰者模式

若要扩展功能,装饰者提供了比集成更有弹性的替代方案,动态地将责任附加到对象上。

装备的超类

public interface IEquip {

    int calcu();

    String descr();

}

各个装备的实现类,如武器

public class ArmEquip implements IEquip {
    @Override
    public int calcu() {
        return 5;
    }

    @Override
    public String descr() {
        return "屠龙宝刀";
    }
}

装饰品的超类

public interface IEquipDecorator extends IEquip {
}

装饰品的实现类

public class BlueGemDecotator implements IEquipDecorator {

    private IEquip equip;

    public BlueGemDecotator(IEquip equip) {
        this.equip = equip;
    }

    @Override
    public int calcu() {
        return 10 + equip.calcu();
    }

    @Override
    public String descr() {
        return equip.descr() + " 点击就送";
    }
}
public class Test {

    public static void main(String[] args) {
        IEquip equip = new BlueGemDecotator(new ArmEquip());
        //IEquip equip = new BlueGemDecotator(new BlueGemDecotator(new ArmEquip()));
        System.out.println("攻击力:" + equip.calcu());
        System.out.println("装备描述:" + equip.descr());
    }

}

命令模式

将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。(简化: 将请求封装成对象,将动作请求者和动作执行者解耦。)

家电API

public class Door {

    public void open() {
        System.out.println("打开门……");
    }

    public void close() {
        System.out.println("关闭门……");
    }

}

统一的命令接口

public interface Command {

    void execute();

}

家电实现该接口

public class DoorOpenCommand implements Command {

    private Door door;

    public DoorOpenCommand(Door door) {
        this.door = door;
    }

    @Override
    public void execute() {
        door.open();
    }
}

遥控器

public class Control {

    private static final int CONTROL_SIZE = 9;

    // 遥控器按钮  一共9个按钮
    private Command[] commands;

    public Control() {
        commands = new Command[CONTROL_SIZE];
        for (int i = 0; i < CONTROL_SIZE; i++) {
            commands[i] = new NoCommand();
        }
    }

    /**
     * 设置每个按钮对应的位置
     */
    public void setCommands(int index, Command command) {
        commands[index] = command;
    }

    /**
     * 模拟点击按钮
     */
    public void press(int index) {
        commands[index].execute();
    }

}

定义一个命令,可以运行一系列操作

public class QuickCommand implements Command {

    private Command[] commands;

    public QuickCommand(Command[] commands) {
        this.commands = commands;
    }

    @Override
    public void execute() {
        for (Command command : commands) {
            command.execute();
        }
    }
}

测试

public class Test {

    public static void main(String[] args) {
        Control control = new Control();
        Door door = new Door();
        // 执行单个命令
        control.setCommands(1, new DoorOpenCommand(door));
        control.press(1);

        // 执行批量命令
        QuickCommand mutils = new QuickCommand(new Command[]{new DoorOpenCommand(door), new DoorCloseCommand(door)});
        control.setCommands(3, mutils);
        control.press(3);

        control.press(5);
    }

}

策略模式

现实生活中,我们要做一件事情或者完成某项工作,往往有很多种途径。比如我们现在线下的支付方式有了很多种选择,只要我们手机在身上,就可以用微信或支付宝。

在软件设计层面,我们把各种支付方式叫做策略。如果不考虑设计模式的话,我们可能会在一个类中用if…else方式来选择支付方式,但如果以后要改变支付方式,比如不能用微信支付了,或者新增了其他支付方式,我们就要改变这个类,这会带来代码维护的麻烦。

算法体现了几个设计原则,第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而不是具体类(定义了策略接口);第三、多用组合,少用继承(客户通过组合方式使用策略)。​

从王者荣耀看设计模式

定义召唤师技能接口

public interface ISkill {

    /**
     * 使用召唤师技能
     */
    abstract void useSkill();

}

实现各个技能,如“疾跑”,后者“闪现”

public class JiPao implements ISkill {
    @Override
    public void useSkill() {
        System.out.println("疾跑,增加30%移动速度");
    }
}

定义英雄,抽象类(抽取公共)

public abstract class Hero {

    // 英雄名称
    private String heroName;

    // 召唤师技能
    private ISkill iSkill;

    // 英雄自我介绍
    public abstract void display();

    // 英雄普通攻击
    public abstract void normalAttack();

    public void skill() {
        iSkill.useSkill();
    }

    // get/set
}

实现具体的英雄,如“后羿”

public class HouYi extends Hero {

    public HouYi() {
        super.setHeroName("后羿");
    }

    @Override
    public void display() {
        System.out.println("我是后羿,最强射手");
    }

    @Override
    public void normalAttack() {
        System.out.println("xiuxiuxiu");
    }
}

下面是测试

public static void main(String[] args) {
    // 选择英雄
    Hero hero = new HouYi();
    // 英雄自我介绍
    hero.display();
    // 选择召唤师技能
    hero.setiSkill(new JiPao()); // 面向接口编程
    // 游戏开始
    // 普通攻击
    hero.normalAttack();
    // 使用技能
    hero.skill();
}

除该场景外,我们还可以应用于支付通道,用于多个支付通道的路由选择,及减少后期由于通道增减带来的代码维护难度

责任链模式

在这种模式中,通常每个接收者都包含对另一个接收者的引用。

public abstract class AbstractLogger {

    public static int INFO = 1;
    public static int DEBUG = 2;
    public static int ERROR = 3;

    protected int level;

    protected AbstractLogger nextLogger;

    public void setNextLogger(AbstractLogger nextLogger) {
        this.nextLogger = nextLogger;
    }

    public void log(int level, String message) {
        if (this.level <= level) {
            write(message);
        }
        if (nextLogger != null) {
            nextLogger.log(level, message);
        }
    }

    abstract protected void write(String message);

}

多个Logger

public class ConsoleLogger extends AbstractLogger {

    public ConsoleLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("ConsoleLogger=" + message + ", level=" + this.level);
    }
}

测试类

public class Test {

    private static AbstractLogger getChainLoggers() {
        ConsoleLogger consoleLogger = new ConsoleLogger(AbstractLogger.DEBUG);
        ErrorLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        FileLogger fileLogger = new FileLogger(AbstractLogger.INFO);

        consoleLogger.setNextLogger(errorLogger);
        errorLogger.setNextLogger(fileLogger);

        return consoleLogger;
    }

    public static void main(String[] args) {
        AbstractLogger abstractLogger = getChainLoggers();
        abstractLogger.log(AbstractLogger.DEBUG, "Hello World");
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值