设计模式----迪米特法则与外观模式

迪米特法则:

/**
 * @author 陈柏宇
 * 迪米特法则,又称最少知识原则
 * 如果两个类不必直接通信,那么这两个类就不应当直接发生直接的相互作用。
 * 如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
 *
 * 迪米特法则首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限。
 * 也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或方法就不要公开。
 *
 * 迪米特法则的根本思想是强调类之间的松耦合,类之间的耦合越弱,越有利于复用,一个处在弱耦合
 * 的类被修改,不会对有关系的类造成波及。
 */

比如我们使用了MVC三层架构,那么页面和数据库的交互就要通过服务层,页面不用直接去访问数据,交给服务层去做就好了。

外观模式:

 

/**
 * @author 陈柏宇
 * 外观模式:
 * 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,
 * 这个接口使得这一子系统更加容易使用
 */

 

我们先来看看这个设计模式的UML类图。

其实这个设计模式在我的项目中也有体现。

我们先来看看模板

/**
 * @author 陈柏宇
 * 子系统类1
 */

public class SubSystem1 {
    public void Method1()
    {
        System.out.println("子系统方法一");
    }
}
/**
 * @author 陈柏宇
 * 子系统类2
 */

public class SubSystem2 {
    public void Method2()
    {
        System.out.println("子系统方法二");
    }
}
/**
 * @author 陈柏宇
 * 子系统类3
 */

public class SubSystem3 {
    public void Method3()
    {
        System.out.println("子系统方法三");
    }
}
/**
 * @author 陈柏宇
 * 子系统类4
 */

public class SubSystem4 {
    public void Method4()
    {
        System.out.println("子系统方法四");
    }
}

外观类:

public class Facade {
    private SubSystem1 one;
    private SubSystem2 two;
    private SubSystem3 three;
    private SubSystem4 four;

    public Facade()
    {
        one = new SubSystem1();
        two = new SubSystem2();
        three = new SubSystem3();
        four = new SubSystem4();
    }

    public void methodA()
    {
        System.out.println("方法组A");
        one.Method1();
        two.Method2();
        four.Method4();
    }
    public void methodB()
    {
        System.out.println("方法组B");
        three.Method3();
    }
}

main函数:

public static void main(String[] args) {
        Facade f = new Facade();
        f.methodA();
        f.methodB();
    }

输出:

方法组A
子系统方法一
子系统方法二
子系统方法四
方法组B
子系统方法三

客户只需要调用两个方法就可以实现繁琐的子系统类的方法了,那么这个设计模式的应用场景是啥呢?

/**
 * @author 陈柏宇
 *
 * 外观模式的使用场景:
 * 首先在设计初期阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构MVC
 * 就要考虑在数据访问层和业务逻辑层,业务逻辑层和表示层的层与层之间建立外观Facade
 *
 * 其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数模式在使用的时候
 * 会产生很多很多的小类,这本来是一件好事,但是也给外部调用它们的用户带来了使用上的困难,
 * 增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。
 *
 * 第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含了非常重要的内容,
 * 新的需求开发必须要依赖于它,此时使用外观模式Facade也是非常合适的,我们可以为一个新系统开发一个外观Facade类,
 * 来提供设计粗糙的或者高度复杂的遗留代码的比较清晰的简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互。
 */

现在我们来看一个具体的例子:

购买股票例子。

如果一个用户直接购买股票其实是一件非常耗费精力的事,因为市场中有很多股票,你要去购买的话首先要对这种行业十分了解,

而用户不可能一一了解,这个时候基金的优势就体现出来了。

基金是由相对专业的人士负责处理的,这个人会收集用户的钱,把资金投入前景很好的股票,这样用户就不用耗费精力去了解市场中的股票了,

只要把钱投入基金中就可以回家睡觉了。

我们现在看看代码:

/**
 * @author 陈柏宇
 * 股票1
 */

public class Stock1 {
    public void buy()
    {
        System.out.println("股票1的买入");
    }
    public void sell()
    {
        System.out.println("股票1的卖出");
    }
}
/**
 * @author 陈柏宇
 * 股票2
 */

public class Stock2 {
    public void buy()
    {
        System.out.println("股票2的买入");
    }
    public void sell()
    {
        System.out.println("股票2的卖出");
    }
}
/**
 * @author 陈柏宇
 * 股票3
 */

public class Stock3 {
    public void buy()
    {
        System.out.println("股票3的买入");
    }
    public void sell()
    {
        System.out.println("股票3的卖出");
    }
}
/**
 * @author 陈柏宇
 * 国债1
 */

public class NationalDebt1 {
    public void buy()
    {
        System.out.println("国债1的买入");
    }
    public void sell()
    {
        System.out.println("国债1的卖出");
    }
}
/**
 * @author 陈柏宇
 * 国债2
 */

public class NationalDebt2 {
    public void buy()
    {
        System.out.println("国债2的买入");
    }
    public void sell()
    {
        System.out.println("国债2的卖出");
    }
}

基金类:

/**
 * @author 陈柏宇
 * 基金类,使用了外观模式
 */

public class Fund {
    Stock1 stock1;
    Stock2 stock2;
    Stock3 stock3;
    NationalDebt1 nationalDebt1;
    NationalDebt2 nationalDebt2;
    public Fund()
    {
        stock1 = new Stock1();
        stock2 = new Stock2();
        stock3 = new Stock3();
        nationalDebt1 = new NationalDebt1();
        nationalDebt2 = new NationalDebt2();
    }

    public void BuyFund()
    {
        stock1.buy();
        stock2.buy();
        stock3.buy();
        nationalDebt2.buy();
        nationalDebt1.buy();
    }

    public void SellFund()
    {
        stock1.sell();
        stock2.sell();
        stock3.sell();
        nationalDebt1.sell();
        nationalDebt2.sell();
    }
}

main函数:

/**
 * @author 陈柏宇
 * 我们如果采用基金类,那么用户根本就不用知道股票的具体细节,投资基金就可以回家睡觉了,一段时间就可以赎回自己的钱了,
 * 十分方便。
 */

public class FundTest {
    public static void main(String[] args) {

        Fund fund = new Fund();
        fund.BuyFund();
        fund.SellFund();

    }
}

控制台输出:

股票1的买入
股票2的买入
股票3的买入
国债2的买入
国债1的买入
股票1的卖出
股票2的卖出
股票3的卖出
国债1的卖出
国债2的卖出

 

posted @ 2021-09-07 21:47  Apak陈柏宇  阅读(180)  评论(0编辑  收藏  举报