2016-12-28 外观模式 + 适配器模式

来源:互联网 发布:数据库相关书籍 编辑:程序博客网 时间:2024/06/04 19:17

外观模式、门面模式

示例:

// 股票1

class Stock1 {

    public void Sell() {

        Console.WriteLine(“股票1卖出”);

    }

    public void Buy() {

        Console.WriteLine(“股票1买入”);

    }

}


// 股票2

class Stock2 {

    // 代码类似股票1略

}


// 股票3

class Stock3 {

    // 代码类似股票1略

}


class NationalDebt1 {    // 国债1

    // 代码类似股票1略

}


class Realty1 {    // 房地产1

    // 代码类似股票1略

}


// 客户端代码

static void Main(string[] args) {

    Stock1  gu1 = new Stock1();

    Stock2 gu2 = new Stock2();

    Stock3 gu3 = new Stock3();

    NationalDebt1 nd1 = new NationalDebt1();

    Realty1 rt1 = new Realty1();


    gu1.Buy();

    gu2.Buy();

    gu3.Buy();

    nd1.Buy();

    rt1.Buy();


    gu1.Sell();

    gu2.Sell();

    gu3.Sell();

    nd1.Sell();

    rt1.Sell();


    Console.Read();

} // 用户需要了解国债、股票、房产情况,需要参与这些项目的具体买和卖;耦合性高。


引入基金类:

class Fund {

    Stock1 gu1;

    Stock2 gu2;

    Stock3 gu3;

    NationalDebt1 nd1;

    Realty1 rt1;

    public Fund() {

        gu1 = new Stock1();

        gu2 = new Stock2();

        gu3 = new Stock3();

        nd1 = new NationalDebt1();

        rt1 = new Realty1();

    }

    public void BuyFund() {

        gu1.Buy();

        gu2.Buy();

        gu3.Buy();

        nd1.Buy();

        rt1.Buy();

    }

    public void SellFund() {

        gu1.Sell();

        gu2.Sell();

        gu3.Sell();

        nd1.Sell();

        rt1.Sell();

    }

}


// 客户端如下

static void Main(string[] args) {

    Fund jijin = new Fund();

    // 基金购买

    jijin.BuyFund();

    // 基金赎回

    jijin.SellFund();

    Console.Read;

} // 此时用户只需要了解基金即可,客户端非常简洁明了。


    外观模式Facade,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更容易使用。Facade外观类知道哪些子系统类负责处理请求,将客户端的请求代理给适当的子系统对象。子系统类集合(SubSystem Classes)实现了系统的功能,处理Facade对象指派的任务。注意子类中没有Facade的任何信息,即没有对Facade对象的引用。


class SubSystemOne {

    public void MethodOne() {

        Console.WriteLine(“ 子系统方法一”);

    }

}


class subSystemTwo {

    public void MethodTwo() {

        Console.WriteLine(“ 子系统方法二”);

    }

}


class SubSystemThree {

    public void MethodThree() {

        Console.WriteLine(“ 子系统方法三”);

    }

}


class SubSystemFour {

    public void MethodThree() {

        Console.WriteLine(“ 子系统方法四”);

    }

}


// 外观类,他需要了解多有的子系统的方法或属性,进行组合,以备外界调用

class Facade {

    SubSystemOne one;

    SubSystemTwo two;

    SubSystemThree three;

    SubSystemFour four;


    public Facade() {

        one = new SubSystemOne();

        two = new SubSystemTwo();

        three = new SubSystemThree();

        four = new SubSystemFour();

    }


    public void MethodA() {

        Console.WriteLine(“\n方法组A() —— ”);

        one.MethodOne();

        two.MethodTwo();

        four.MethodFour();

    }

    public void MethodB() {

        Console.WriteLine(“\n方法组B() —— ”);

        two.MethodTwo();

        three.MethodThree();

    }

}

// 客户端调用,由于Facade的作用,客户端可以根本不知三个子系统类的存在

static void Main(string[] args) {

    Facade facade = new Facade();

    facade.MethodA();

    facade.MethodB();


    Console.Read();

} // 外观模式完美地体现了依赖倒转原则和迪米特法则的思想,所以是常用模式之一。


    首先,在设计初期阶段,应该要有意识的将不同的各层分离,比如经典的三层架构,就可以考虑在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间建立外观Facade,这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。

    其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,但也给外部调用他们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少他们之间的依赖。

    第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。


适配器模式

    如欧洲插座经过适配器 可以供美国插头使用,OO适配器和真实世界的适配器扮演着同样的角色,将一个接口转换成另一个接口,以符合客户的期望。适配起就像两个不同厂商之间的中间人。

案例:一个飞起来叫起来都像鸭子的小动物可能是装了鸭子适配器的火鸡

// 鸭子接口

public interface Duck {

    public void quack();

    public void fly();

}

// 鸭子的子类

public class MallarDuck implements Duck {

    public void quack() {

        System.out.printIn(“Quack”);

    }

    public void fly() {

        System.out.printIn(“I’m flying.”);

    }

}


// 火鸡接口

public interface Turkey {

    public void gobble();

    public void fly();

}

// 火鸡类

public class WildTurkey implements Turkey {

    public void gobble() {

        System.out.printIn(“Gobble gobble.”);

    }

    public void fly() {

        System.out.printIn(“I’m flying a short distance.”);

    }

}


现在因缺少鸭子对象,需要用一只火鸡替代,现在我们要把一只火鸡伪装成鸭子

public class TurkeyAdapter implements Duck { // 实现Duck接口的适配器

    Turkey turkey;

    public TurkeyAdapter(Turkey turkey) {

        this.turkey = turkey;

    }

    public void quack() {

        turkey.gobble();

    }

    public void fly() {

        for(int i=0;i<5;i++) {

            turkey.fly(); // 由于火鸡的飞行距离短,不得多次调用以模仿鸭子的行为。

        }

    }

}


    适配器模式解析

        客户是根据目标接口实现的,而适配器持有被适配对象且根据被适配者提供的接口实现了目标接口。这样客户和被适配者之间相互解耦,互补知道对方的存在。

    一个适配器只能封装一个类吗?

        通常是这样的,但现实是复杂的,有时需要让一个适配器包装多个被适配者。这涉及另一个模式,称为外观模式。

    定义:

        将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。

    在可以多重继承的语言中还有一种类适配器,它使用多重继承的方法解决问题而不是像上述对象适配器那样使用组合。

    装饰者 :不改变接口,但加入责任;适配器:将一个接口转成另一个接口;外观:让接口更简单


外观模式

    外观只是提供你更直接的操作,并未将原来的子系统阻隔起来。如果你需要子系统类的更低层功能,还是可以用原来的子系统。

    外观模式没有封装接口,只是提供简化的接口。所以用户如果觉得有必要依然可以使用子系统的类。

    你可以为子系统创建多个外观,也可以通过外观模式组合出新的功能,就像部分之和不等于整体。


    外观模式与适配器模式的不同之处在于它们的目标不同,适配器模式的意图是,“改变”接口符合客户的期望,而外观模式的意图是,提供子系统的一个简化接口。外观不仅仅简化接口,也将客户从组建的子系统中解耦。


    外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。外观模式的意图是提供一个简单的接口,好让一个子系统更易于使用。





软件设计愿则

封装变化

多用组合,少用继承

针对接口编程,不针对实现编程

为交互对象之间的松耦合设计而努力

类应该对扩展开放,对修改关闭

依赖抽象,不要依赖具体类

只和朋友交谈


0 0
原创粉丝点击