package com.yj.cloudprint.enterprise.confg.webcontext.test;

public class Test {

    // 1.在思考过程中时刻具备扩展意识、抽象意识、封装意识。23种设计模式中体会、看源码、好项目中从设计入手多分析总结。
    // 一.开闭原则
    // 1.一个本子已经写完,不可能撕几张纸粘上去,最好是买个新的本子。如下一个qq验证完的方法,添加时候微信放在一起,最好是新起个类验证,如此类推
    // 2.做好的功能、或添加新功能(程序本来是健康),应该在已有的基础上扩展、模块、类、方法。而不是修改。因为修改往往会造成原有的报错

    // 3.开闭原则核心在设计之初能够用一些基本的原则进行一些约束,预留扩展点。扩展点方法有多态、依赖注入、针对接口编程、以及设计模式。
    // 这些扩展点抽象化运用。分离可变和不可变。不可变封装在对象里

    static class User {
        private String userName;//用户名
        private String passWord;//密码
    }

    /**
     * 定义约束-抽象化接口
     * 功能验证器
     */
    interface Verification {
        boolean validate(User user);
    }

    /**
     * qq 验证
     */
    static class QQ implements Verification {

        @Override
        public boolean validate(User user) {
            return false;
        }
    }

    /**
     * 微信验证
     */
    static class Wx implements Verification {

        @Override
        public boolean validate(User user) {
            return false;
        }
    }

    /**
     * 验证服务
     */
    static class AuthService {

        // 依赖注入抽象验证器对象(运用多态)
        private Verification verification;

        //通过构造器注入qqAuther对象
        public AuthService(Verification validate) {
            this.verification = validate;
        }

        public boolean verifcationUser(User user) {
            return verification.validate(user);
        }
    }

    // web 调用
    public static void main(String[] args) {
        User user = new User();
        QQ qq = new QQ();
        boolean b = new AuthService(qq).verifcationUser(user);

        Wx wx = new Wx();
        boolean b1 = new AuthService(wx).verifcationUser(user);

        // 下面各种程序校验
    }

    // 二、里氏替换原则
    // 里氏替换和父子多态相似,但是不一样,容易搞混,我理解多态 返回、对象、参数、变量是更广阔的实现类型(Object - user)。
    // 子类比父类功能强大User user = (User) object。类似语法

    // 里氏替换就是子类完美继承父类的设计初衷,并做了增强。   包括继承方法设计细节约束
    // 违法里氏替换原则

    //  1.违法实现的功能
    // 父类定义从小到大排序的方法输出。子类实现就从大到小实现输出。违法约定

    //  2.方法输入参数、返回参数、异常抛出
    //   父类方法定义运行出错返回null,数据为空返回空集合或对象。
    //   而子类实现方法运行出错抛异常Ex. 数据为空,返回null。违法约定

    //   项目中观察,父类定义方法后面会抛异常类型。子类就只能抛定义父类的异常。不能比父类异常更高或低

    //   父类定义的方法输入如何负整数,子类方法实现限制负数的输入。违法约定

    //  你可以改变子类的实现逻辑,但是不能改变约定的协议

    // 里式替换是细力度的开闭原则。这个准则应用的场景,往往是在方法功能的调整上,
    // 要达到的效果是:该方法对已经调用的代码的效果不变,并能支撑新的功能或提供更好的性能。
    // 换句话说,就是在保证兼容的前提条件下做扩展和调整。

    // 三、迪米特原则
    // 去商店买东西,结账肯定不会直接把钱包给收银员,让收银员自己拿钱,而是你从钱包里面把钱拿出来给收银员
    // 钱包就是对象,钱就是参数。
    // 迪米特法则是从关系出发

    // 如下实现:客户不能把钱包对象给收银员
    // 不该有直接依赖关系的类之间,不要有依赖

    // 如下实现:客户有钱包支付,可能是手机支付,就要提取成接口抽象。
    // 有依赖关系的类之间,尽量只依赖必要的接口。

    //迪特米法则带来的问题也是很明显的:即会在系统中造出大量的小方法散落在系统的各个角落,
    // 这些方法仅仅是传递消息的调用,与系统的业务逻辑没有任何关系
    // 如果把钱包换成Map对象,封装方法调用。

    // 如下操作
    // 收银员
    static class A {
        public static void main(String[] args) {
            A a = new A();
            System.out.println("收银员开始要多少钱");
            a.testA(new B());

        }

        // 收银员执行要钱(客户)
        public void testA(B b) {
            // testA方法不满足迪特米原则,C钱包 和A收银员类 没有直接依赖关系
            C c = b.testBB();
            c.testC();

            // 改进
            String s = b.testB();
            System.out.println("收银员收" + s);
        }
    }

    //客户
    static class B {
        // 钱包
        private C a = new C();

        // 不满足迪特米原则,返回钱包类给收银员
        public C testBB() {
            return a;
        }

        // 改进
        // 客服从钱包里面拿钱出来
        public String testB() {
            System.out.println("客户执行数钱动作");
            return a.testC();
        }
    }

    // 钱包
    static class C {
        public String testC() {
            return "钱";
        }
    }

}

// 钱包
interface Wallet {
    String money();
}

//手机钱包
interface ModpayWallet {
    String ModMoney();
}

// 人名币   四、这里用到接口隔离原则,每个接口类负责一种业务
class ChinesYuan implements Wallet, ModpayWallet {

    @Override
    public String money() {
        return null;
    }

    @Override
    public String ModMoney() {
        return null;
    }
}

// 五、依赖倒置,依赖抽象,例如对象有抽象类型,可以使用这个对象做抽象变量引用。
// 抽象层次高,稳定性就越高,倒置就是复用的重点在抽象层上