精华内容
下载资源
问答
  • 外观模式

    2018-12-09 18:31:41
    1.什么是外观模式?(解释:说白了就是封装多个操作成一个操作) 外观模式(Facade Pattern)门面模式,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问...2.举例说明 用户注册完之后,需要调用阿里短信接...

    1.什么是外观模式?解释:说白了就是封装多个操作成一个操作)
    外观模式(Facade Pattern)门面模式,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性。
    这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。

    2.举例说明
    用户注册完之后,需要调用阿里短信接口、邮件接口、微信推送接口。(3个操作如果一个个地调用太麻烦,不如把这3个操作封装成一个操作

    public interface EamilSmsService {
    	  public void sendSms();	
    }
    public class EamilSmsServiceImpl implements   EamilSmsService{
    	public void sendSms() {
    		System.out.println("发送邮件消息");
    		
    	}
    }
    
    //微信消息推送
    public interface WeiXinSmsService {
      public void sendSms();	
    }
    public class EamilSmsServiceImpl implements   EamilSmsService{
    
    	@Override
    	public void sendSms() {
    		System.out.println("发送邮件消息");
    		
    	}
    
    }
    
    //阿里短信消息
    public interface AliSmsService {
    	public void sendSms();
    }
    public class AliSmsServiceImpl implements AliSmsService {
    	@Override
    	public void sendSms() {
         System.out.println("支付宝发送消息...");
    	}
    }
    

    最后来写门面类(对多个操作封装之后的整体)

    public class Computer {
    	AliSmsService aliSmsService;
    	EamilSmsService eamilSmsService;
    	WeiXinSmsService weiXinSmsService;
    
    	public Computer() {
    		aliSmsService = new AliSmsServiceImpl();
    		eamilSmsService = new EamilSmsServiceImpl();
    		weiXinSmsService = new WeiXinSmsServiceImpl();
    	}
    
    	public void sendMsg() {
    		aliSmsService.sendSms();
    		eamilSmsService.sendSms();
    		weiXinSmsService.sendSms();
    
    	}
    
    }
    

    最后当客户端需要调用这3个操作时,可以这样

    public class Client {
    	public static void main(String[] args) {
    		// AliSmsService aliSmsService= new AliSmsServiceImpl();
    		// EamilSmsService eamilSmsService= new EamilSmsServiceImpl();
    		// WeiXinSmsService weiXinSmsService= new WeiXinSmsServiceImpl();
    		// aliSmsService.sendSms();
    		// eamilSmsService.sendSms();
    		// weiXinSmsService.sendSms();
    		new Computer().sendMsg();
    	}
    }
    
    展开全文
  • 设计模式之外观模式

    2019-11-17 09:21:18
    概念:外观模式,也叫过程模式,外观模式为各个子系统或者子对象提供了一致的高层接口,通过定义一个高层接口,用以屏蔽内部子系统的实现细节,使得客户端不直接与各个子系统进行关联,而是直接调用高层接口提供的...

    一、简介

    • 概念:外观模式,也叫过程模式,外观模式为各个子系统或者子对象提供了一致的高层接口,通过定义一个高层接口,用以屏蔽内部子系统的实现细节,使得客户端不直接与各个子系统进行关联,而是直接调用高层接口提供的方法。外观模式也属于结构性模式。
    •  
    • 传统方式原理图:客户端直接依赖各个子系统,这样子系统发生一点变化,客户端就要改,不符合开闭原则。

    可见,客户端直接调用各个子系统的接口。 

    • 外观模式原理图

    可见,使用外观模式后,客户端不直接调用各个子系统的接口,而是调用外观模式提供的简化之后的接口,当然客户端还是可以调用各个子系统的接口的。在客户端和各个子系统中增加一个高层接口,即如上图的Facade外观类,使得客户端直接与外观类进行关联,而不是与各个子系统关联,无须关心子系统实现细节。 

    二、角色分析

    • a. 外观类:就是上面所说的高层接口,为客户端提供统一的调用接口,请求只会转发到外观类,然后由外观类决定调用哪一个具体的子系统处理请求。(有点类似代理的概念,让代理给你转发请求)
    • b. 调用者:客户端,即直接与外观类关联;
    • c. 各个子系统:处理外观类对象指派的任务,具体功能的实际提供者,外观类的调用转发到子系统中来完成;

    三、示例

    下面我们以一个生活中再熟悉不过的例子来说明外观模式,相信大家都会做菜吧哈哈,每天做饭的大体步骤是不是:

    买菜 -> 洗菜 -> 打开抽油烟机 -> 烹饪食物 -> 关闭抽油烟机 -> 洗碗吃饭 -> 搞定

    大体类图:

    通过UML类图可以很明显地客户端不会直接依赖各个子系统,而是通过外观类间接地依赖。

    详细代码如下:

    【a】食物类:这里使用了双重检查机制的单例模式获取实例

      

    public class Food {
    
        private static volatile Food food;
    
        private Food() {
        }
    
        public static Food getInstance() {
            if (null == food) {
                synchronized (Food.class) {
                    if (null == food) {
                        food = new Food();
                    }
                }
            }
            return food;
        }
    
        public void buyFood() {
            System.out.println("购买食物...");
        }
    
        public void washing() {
            System.out.println("清洗食物...");
        }
    
        public void cooking() {
            System.out.println("烹饪食物...");
        }
    
    }

    【b】碗:这里使用了双重检查机制的单例模式获取实例

    public class Bowl {
    
        private static volatile Bowl bowl;
    
        private Bowl() {
        }
    
        public static Bowl getInstance() {
            if (null == bowl) {
                synchronized (Bowl.class) {
                    if (null == bowl) {
                        bowl = new Bowl();
                    }
                }
            }
            return bowl;
        }
    
        public void washing() {
            System.out.println("洗碗...");
        }
    
    }

    【c】油烟机

    public class LampblackMachine {
    
        private static volatile LampblackMachine lampblackMachine;
    
        private LampblackMachine() {
        }
    
        public static LampblackMachine getInstance() {
            if (null == lampblackMachine) {
                synchronized (LampblackMachine.class) {
                    if (null == lampblackMachine) {
                        lampblackMachine = new LampblackMachine();
                    }
                }
            }
            return lampblackMachine;
        }
    
        public void open() {
            System.out.println("打开抽油烟机...");
        }
    
        public void close() {
            System.out.println("关闭抽油烟机...");
        }
    
    }

    【d】外观类

    public class CookingFacade {
        /**
         * 持有各个子对象的引用
         */
        private Bowl bowl;
        private Food food;
        private LampblackMachine lampblackMachine;
    
        public CookingFacade() {
            this.bowl = Bowl.getInstance();
            this.food = Food.getInstance();
            this.lampblackMachine = LampblackMachine.getInstance();
        }
    
        /**
         * 准备阶段: 买菜、洗菜、打开油烟机
         */
        public void ready() {
            food.buyFood();
            food.washing();
            lampblackMachine.open();
        }
    
        /**
         * 烹饪阶段: 煮菜
         */
        public void cooking() {
            food.cooking();
        }
    
        /**
         * 结束阶段: 关闭油烟机、洗碗
         */
        public void end() {
            lampblackMachine.close();
            bowl.washing();
        }
    
    }

    【e】客户端

    public class Client {
        public static void main(String[] args) {
            CookingFacade facade = new CookingFacade();
            //客户端简化了调用过程,通过调用外观高层接口直接依赖具体的各个子系统完成对应的功能
            facade.ready();
            facade.cooking();
            facade.end();
        }
    }

    【f】运行结果

    可见,一个比较复杂的流程在客户端调用的时候简化了很多,如果是直接调用各个子系统的话,后期不好扩展。

    四、应用案例分析

    Mybatis中org.apache.ibatis.session.Configuration类的newMetaObject(Object object)就使用了外观模式。下面简要分析一下其中设计外观模式的源码:

    //Configuration.java
    //Configuration持有一些子对象的引用,然后传入MetaObject类中构造方法
    protected ReflectorFactory reflectorFactory;
    protected ObjectFactory objectFactory;
    protected ObjectWrapperFactory objectWrapperFactory;
    //....
    
    public Configuration() {
         //....
        this.reflectorFactory = new DefaultReflectorFactory();
        this.objectFactory = new DefaultObjectFactory();
        this.objectWrapperFactory = new DefaultObjectWrapperFactory();
        //....
    }
    
    //这里实际上就是通过各个子系统去创建MetaObject对象,对外提供了一个高层简化接口,解耦客户端和各个子系统
    public MetaObject newMetaObject(Object object) {
        //调用MetaObject的静态方法forObject
        return MetaObject.forObject(object, this.objectFactory, this.objectWrapperFactory, this.reflectorFactory);
    }
    
    //MetaObject.java
    //forObject方法
    public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
        //调用构造方法
        return object == null ? SystemMetaObject.NULL_META_OBJECT : new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
    }
    
    //构造方法
    private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
        this.originalObject = object;
        this.objectFactory = objectFactory;
        this.objectWrapperFactory = objectWrapperFactory;
        this.reflectorFactory = reflectorFactory;
        if (object instanceof ObjectWrapper) {
            this.objectWrapper = (ObjectWrapper)object;
        } else if (objectWrapperFactory.hasWrapperFor(object)) {
            this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
        } else if (object instanceof Map) {
            this.objectWrapper = new MapWrapper(this, (Map)object);
        } else if (object instanceof Collection) {
            this.objectWrapper = new CollectionWrapper(this, (Collection)object);
        } else {
            this.objectWrapper = new BeanWrapper(this, object);
        }
    }

    角色分析:

    • 子系统对象:this.objectFactory, this.objectWrapperFactory, this.reflectorFactory,具体完成某项功能的类;
    • 外观对象:Configuration类,提供高层接口的类;

    五、总结

    优点:

    • a. 对外隐藏了各个子系统的内部实现细节,降低了客户端对各个子系统的使用复杂度;
    • b. 解耦了客户端和子系统,让各个子系统的功能更容易维护和扩展;

    缺点:

    • a. 不能很好地限制客户使用子系统类,即客户端还是可以直接调用各个子系统相关方法;
    • b. 增加新的子系统可能需要修改外观类或客户端的源代码,违反“开闭原则”;

    适用场景:

    • a. 当需要维护一个已经很难扩展和维护的旧系统时,可以考虑为新系统提供一个高层接口,用于与旧系统的对接,方便接口调用;
    • b. 当系统需要分层设计时,可以考虑使用外观模式;
    • c. 当需要简化一个很大的接口或者一组复杂的接口时,可以考虑使用外观模式;
    展开全文
  • 本篇文章介绍一种设计模式——外观模式。本篇文章内容参考《JAVA与模式》之门面模式,外观模式,深入浅出外观模式(二)。 一、外观模式概述1.定义外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个...

    本篇文章介绍一种设计模式——外观模式。本篇文章内容参考《JAVA与模式》之门面模式外观模式深入浅出外观模式(二)

    一、外观模式概述

    1.定义

    外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

    2.定义阐述

    医院的例子

    现代的软件系统都是比较复杂的,设计师处理复杂系统的一个常见方法便是将其“分而治之”,把一个系统划分为几个较小的子系统。如果把医院作为一个子系统,按照部门职能,这个系统可以划分为挂号、门诊、划价、化验、收费、取药等。看病的病人要与这些部门打交道,就如同一个子系统的客户端与一个子系统的各个类打交道一样,不是一件容易的事情。

    首先病人必须先挂号,然后门诊。如果医生要求化验,病人必须首先划价,然后缴费,才可以到化验部门做化验。化验后再回到门诊室。

    上图描述的是病人在医院里的体验,图中的方框代表医院。

    解决这种不便的方法便是引进外观模式,医院可以设置一个接待员的位置,由接待员负责代为挂号、划价、缴费、取药等。这个接待员就是外观模式的体现,病人只接触接待员,由接待员与各个部门打交道。

    二、外观模式结构

    外观模式没有一个一般化的类图描述,最好的描述方法实际上就是以一个例子说明。

    由于门面模式的结构图过于抽象,因此把它稍稍具体点。假设子系统内有三个模块,分别是ModuleA、ModuleB和ModuleC,它们分别有一个示例方法,那么此时示例的整体结构图如下:
      
    在这个对象图中,出现了两个角色:
    ●  外观(Facade)角色 :客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。

    ●  子系统(SubSystem)角色 :可以同时有一个或者多个子系统。每个子系统都不是一个单独的类,而是一个类的集合(如上面的子系统就是由ModuleA、ModuleB、ModuleC三个类组合而成)。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。

    时序图


    子系统角色中的类:

    public class ModuleA {
        //示意方法
        public void testA(){
            System.out.println("调用ModuleA中的testA方法");
        }
    }
    public class ModuleB {
        //示意方法
        public void testB(){
            System.out.println("调用ModuleB中的testB方法");
        }
    }
    public class ModuleC {
        //示意方法
        public void testC(){
            System.out.println("调用ModuleC中的testC方法");
        }
    }

    外观角色类:

    public class Facade {
        //示意方法,满足客户端需要的功能
        public void test(){
            ModuleA a = new ModuleA();
            a.testA();
            ModuleB b = new ModuleB();
            b.testB();
            ModuleC c = new ModuleC();
            c.testC();
        }
    }

    客户端角色类:

    public class Client {
    
        public static void main(String[] args) {
    
            Facade facade = new Facade();
            facade.test();
        }
    
    }

    Facade类其实相当于A、B、C模块的外观界面,有了这个Facade类,那么客户端就不需要亲自调用子系统中的A、B、C模块了,也不需要知道系统内部的实现细节,甚至都不需要知道A、B、C模块的存在,客户端只需要跟Facade类交互就好了,从而更好地实现了客户端和子系统中A、B、C模块的解耦,让客户端更容易地使用系统。

    三、外观模式的扩展

    使用外观模式还有一个附带的好处,就是能够有选择性地暴露方法。一个模块中定义的方法可以分成两部分,一部分是给子系统外部使用的,一部分是子系统内部模块之间相互调用时使用的。有了Facade类,那么用于子系统内部模块之间相互调用的方法就不用暴露给子系统外部了。

    比如,定义如下A、B、C模块。

    public class Module {
        /**
         * 提供给子系统外部使用的方法
         */
        public void a1(){};
    
        /**
         * 子系统内部模块之间相互调用时使用的方法
         */
        public void a2(){};
        public void a3(){};
    }
    public class ModuleB {
        /**
         * 提供给子系统外部使用的方法
         */
        public void b1(){};
    
        /**
         * 子系统内部模块之间相互调用时使用的方法
         */
        public void b2(){};
        public void b3(){};
    }
    public class ModuleC {
        /**
         * 提供给子系统外部使用的方法
         */
        public void c1(){};
    
        /**
         * 子系统内部模块之间相互调用时使用的方法
         */
        public void c2(){};
        public void c3(){};
    }
    public class ModuleFacade {
    
        ModuleA a = new ModuleA();
        ModuleB b = new ModuleB();
        ModuleC c = new ModuleC();
        /**
         * 下面这些是A、B、C模块对子系统外部提供的方法
         */
        public void a1(){
            a.a1();
        }
        public void b1(){
            b.b1();
        }
        public void c1(){
            c.c1();
        }
    }

    这样定义一个ModuleFacade类可以有效地屏蔽内部的细节,免得客户端去调用Module类时,发现一些不需要它知道的方法。比如a2()和a3()方法就不需要让客户端知道,否则既暴露了内部的细节,又让客户端迷惑。

    一个系统可以有几个外观类

    在外观模式中,通常只需要一个外观类,并且此外观类只有一个实例,换言之它是一个单例类。当然这并不意味着在整个系统里只有一个外观类,而仅仅是说对每一个子系统只有一个外观类。或者说,如果一个系统有好几个子系统的话,每一个子系统都有一个外观类,整个系统可以有数个外观类。

    为子系统增加新行为

    初学者往往以为通过继承一个外观类便可在子系统中加入新的行为,这是错误的。外观模式的用意是为子系统提供一个集中化和简化的沟通管道,而不能向子系统加入新的行为。比如医院中的接待员并不是医护人员,接待员并不能为病人提供医疗服务。

    四、外观模式的实例

    1.实例说明

    某软件公司欲开发一个可应用于多个软件的文件加密模块,该模块可以对文件中的数据进行加密并将加密之后的数据存储在一个新文件中,具体的流程包括三个部分,分别是读取源文件、加密、保存加密之后的文件,其中,读取文件和保存文件使用流来实现,加密操作通过求模运算实现。这三个操作相对独立,为了实现代码的独立重用,让设计更符合单一职责原则,这三个操作的业务代码封装在三个不同的类中。

    2.实例类图


    EncryptFacade充当外观类,FileReader、CipherMachine和FileWriter充当子系统类。

    3.实例代码

    FileReader:文件读取类,充当子系统类。

    class FileReader  
        {  
            public string Read(string fileNameSrc)   
            {  
           Console.Write("读取文件,获取明文:");  
                FileStream fs = null;  
                StringBuilder sb = new StringBuilder();  
           try  
                {  
                    fs = new FileStream(fileNameSrc, FileMode.Open);  
                    int data;  
                   while((data = fs.ReadByte())!= -1)   
                    {  
                sb = sb.Append((char)data);  
                   }  
                   fs.Close();  
                   Console.WriteLine(sb.ToString());  
           }  
           catch(FileNotFoundException e)   
                {  
               Console.WriteLine("文件不存在!");  
           }  
           catch(IOException e)   
                {  
               Console.WriteLine("文件操作错误!");  
           }  
           return sb.ToString();  
            }  
        }  

    CipherMachine:数据加密类,充当子系统类。

    class CipherMachine  
        {  
           public string Encrypt(string plainText)   
           {  
           Console.Write("数据加密,将明文转换为密文:");  
           string es = "";  
                char[] chars = plainText.ToCharArray();  
           foreach(char ch in chars)   
                {  
                    string c = (ch % 7).ToString();  
               es += c;  
           }  
                Console.WriteLine(es);  
           return es;  
        }  
        }  

    FileWriter:文件保存类,充当子系统类。

    class FileWriter  
        {  
            public void Write(string encryptStr,string fileNameDes)   
            {  
           Console.WriteLine("保存密文,写入文件。");  
                FileStream fs = null;  
           try  
                {  
                   fs = new FileStream(fileNameDes, FileMode.Create);  
                    byte[] str = Encoding.Default.GetBytes(encryptStr);  
                    fs.Write(str,0,str.Length);  
                    fs.Flush();  
                   fs.Close();  
           }      
           catch(FileNotFoundException e)   
                {  
            Console.WriteLine("文件不存在!");  
           }  
           catch(IOException e)   
                {  
                    Console.WriteLine(e.Message);  
               Console.WriteLine("文件操作错误!");  
           }          
            }  
        }  

    EncryptFacade:加密外观类,充当外观类。

    class EncryptFacade  
        {  
            //维持对其他对象的引用  
             private FileReader reader;  
            private CipherMachine cipher;  
            private FileWriter writer;  
    
            public EncryptFacade()  
            {  
                reader = new FileReader();  
                cipher = new CipherMachine();  
                writer = new FileWriter();  
            }  
    
            //调用其他对象的业务方法  
             public void FileEncrypt(string fileNameSrc, string fileNameDes)  
            {  
                string plainStr = reader.Read(fileNameSrc);  
                string encryptStr = cipher.Encrypt(plainStr);  
                writer.Write(encryptStr, fileNameDes);  
            }  
        }  

    Program:客户端测试类

    class Program  
        {  
            static void Main(string[] args)  
            {  
                EncryptFacade ef = new EncryptFacade();  
                ef.FileEncrypt("src.txt", "des.txt");  
                Console.Read();  
            }  
        }  
    五、外观模式的优点

    ●  松散耦合

    外观模式松散了客户端与子系统的耦合关系,让子系统内部的模块能更容易扩展和维护。

    ●  简单易用

    外观模式让子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要跟众多子系统内部的模块进行交互,只需要跟外观类交互就可以了。

    ●  更好的划分访问层次

    通过合理使用Facade,可以帮助我们更好地划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到外观中,这样既方便客户端使用,也很好地隐藏了内部的细节。

    展开全文
  • I . 外观模式概念 II . 外观模式 适用场景 III . 外观模式 优缺点 IV . 外观模式与其它设计模式的联系与区别 V . 外观模式 代码示例



    I . 外观模式概念



    1 . 外观模式概念 :


    ① 设计模式类型 : 结构型 ;

    ② 标准定义 : 提供一个统一接口 , 用于访问子系统中的一群接口 ;

    ③ 隐藏复杂性目的 : 定义高层级接口 , 让子系统更容易使用 , 目的是隐藏系统的复杂性 ;

    ④ 交互流程 : 多个子系统联合完成一个操作 , 提供一个统一的接口 , 供客户端调用 , 客户端不与每个子系统进行复杂的交互 , 客户端只与提供接口的外观类进行交互 ;


    2 . 外观模式的相关角色 :


    ① 外观角色 : 外观类有自己的方法 , 用户可以通过调用外观类的方法 , 调用子系统提供的功能 ;

    ② 子系统角色 : 可以是若干个处理模块 , 数量 1 个或多个 ;

    ③ 用户角色 : 用户通过外观类调用子系统的功能 ;



    II . 外观模式 适用场景



    外观模式适用场景 :

    ① 子系统复杂 : 子系统复杂 , 通过使用外观模式可以简化调用接口 ;

    ② 层次复杂 : 系统结构层次复杂 , 每个层级都一个使用外观对象作为该层入口 , 可以简化层次间的调用接口 ;



    III . 外观模式 优缺点



    1 . 外观模式优点 :


    ① 简化调用 : 简化复杂系统的调用过程 , 无需对子系统进行深入了解 , 即可完成调用 ;

    ② 降低耦合 : 使用外观模式 , 只与外观对象进行交互 , 不与复杂的子系统直接进行交互 , 降低了系统间的依赖 , 使耦合关系更低 ; 子系统内部的模块更容易扩展和维护 ;

    ③ 层次控制 : 层次结构复杂的系统 , 有些方法需要提供给系统外部调用 , 有些方法需要在内部使用 , 将提供给外部的功能定义在外观类中 , 这样既方便调用 , 也能将系统内部的细节隐藏起来 ;

    ④ 符合迪米特法则 : 最少知道原则 , 用户不需要了解子系统内部的情况 , 也不需要与子系统进行交互 , 只与外观类进行交互 ; 降低了应用层与子系统之间的耦合度 ;


    2 . 外观模式缺点 :


    ① 子系统扩展风险 : 系统内部扩展子系统时 , 容易产生风险 ;

    ② 不符合开闭原则 : 外观模式 , 扩展子系统时 , 不符合开闭原则 ;



    IV . 外观模式与其它设计模式的联系与区别



    1 . 外观模式与中介者模式 :


    ① 外观模式 : 外观模式关注外部用户与子系统之间的交互 ;

    ② 中介者模式 : 中介者模式关注子系统内部之间的交互 ;


    2 . 外观模式与单例模式 : 外观类一般会被定义成单例类 ;


    3 . 外观模式 与 抽象工厂模式 : 外观类中 , 使用抽象工厂模式 , 获取子系统的实例对象 , 子系统内部可以屏蔽外观类 ;



    V . 外观模式 代码示例



    1 . 需求描述 : 实现一个购买商品的功能 , 用户提出购买某件商品 , 首先要查看库存 , 然后付款 , 最后物流发货 ;


    ① 用户与子系统直接交互 : 首先要与仓储子系统交互检查是否有库存 , 然后与支付子系统交互支付货款 , 最后进入物流子系统获取物流编号 ; 使用这种交互方式 , 导致用户与子系统耦合度太高 ;

    ② 引入外观类 : 将与仓储子系统 , 支付子系统 , 物流子系统之间的交互统一交给外观类进行处理 , 用户只需要与外观类对象进行交互 , 这样大大减少了用户与多个子系统之间的耦合度 ;


    2 . 多个子系统代码示例 : 三个子系统分别处理各自业务 ;


    ① 仓储子系统代码 :

    package kim.hsl.design.facade;
    
    /**
     * 仓库子系统
     * 查询是否有库存
     */
    public class StoreService {
        public boolean isStokeAvailable(Goods goods){
            System.out.println("校验是否有库存 : " + goods.toString() + " 有库存");
            return true;
        }
    }
    

    ② 支付子系统代码 :

    package kim.hsl.design.facade;
    
    /**
     * 支付子系统
     * 支付成功返回 true
     */
    public class PaymentService {
        public boolean pay(Goods goods){
            System.out.println("使用银联支付");
            return true;
        }
    }
    

    ③ 物流子系统代码 :

    package kim.hsl.design.facade;
    
    /**
     * 物流子系统
     * 进入发货流程 , 返回物流编号
     */
    public class LogisticsService {
        public String logistics(Goods goods){
            String logisticsNo = "31415926";
            System.out.println(goods + " 进入物流系统 , 运单号为 " + logisticsNo);
            return logisticsNo;
        }
    }
    

    3 . 外观类代码 : 外观类中维护三个子系统模块 , 用户通过 buyGoods 方法 , 作为与三个子系统之间的交互接口 ;

    package kim.hsl.design.facade;
    
    /**
     * 用户购买的统一接口
     * 用户只需要与该类进行交互
     * 该类统一处理 仓储 支付 物流 等购买流程
     */
    public class BuyFacade {
        private LogisticsService logisticsService;
        private PaymentService paymentService;
        private StoreService storeService;
    
        public BuyFacade() {
            storeService = new StoreService();
            paymentService = new PaymentService();
            logisticsService = new LogisticsService();
        }
    
        /**
         * 外观类提供的访问内部三个子系统的接口
         * 客户端只需要调用该方法 , 即可完整商品购买流程
         * @param goods
         */
        public void buyGoods(Goods goods){
            if(storeService.isStokeAvailable(goods)){
                if(paymentService.pay(goods)){
                    logisticsService.logistics(goods);
                }
            }
        }
    }
    

    4 . 商品类代码 :

    package kim.hsl.design.facade;
    
    /**
     * 商品
     */
    public class Goods {
        private String name;
        public Goods(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Goods{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    

    5 . 测试函数入口代码 :

    package kim.hsl.design.facade;
    
    public class Main {
        public static void main(String[] args) {
            Goods goods = new Goods("肥皂");
            BuyFacade buyFacade = new BuyFacade();
            buyFacade.buyGoods(goods);
        }
    }
    

    6 . 最终执行结果 :

    校验是否有库存 : Goods{name='肥皂'} 有库存
    使用银联支付
    Goods{name='肥皂'} 进入物流系统 , 运单号为 31415926
    
    展开全文
  • 黑盒——外观模式

    2019-11-26 15:20:48
    外观模式 ​ Facade Pattern:外观模式,是GoF23种设计模式之中属于结构型模式的一种。外观模式的定义就是为一组接口外面在包装一个一致的接口,通过这个一致的接口再去访问被包装的一组接口。 ​ 说起来可能是有点...
  • 一模式定义 外观模式,是软件工程师常用的一种软件设计模式。...二模式举例 1模式分析 我们借用美食天下菜谱中制作糖醋排骨这一道菜来说明这一模式。   2外观模式静态类图   3代码示例 3.1创...
  • 外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用非常方便。 外观模式...
  • Golang设计模式之外观模式

    千次阅读 2017-09-24 16:46:25
    2. 举例说明那当前比较热门的微服务来说,一套服务(比如说短视频服务)包括若干子服务,如图(a),如:音乐服务,短视频服务,计数服务,推荐子服务等。客户端不同的请求会使用不同的子服务。客户端视
  • 23种设计模式说明与类比举例一、外观模式(Facade)二、适配器模式(Adapter)三、策略模式(Strategy)四、桥接模式(Bridge)五、静态工厂模式(Static Factory,又称简单工厂,非23种模式之一)六、工厂方法模式...
  • 3. 外观模式应用实例下面通过一个应用实例来进一步学习和理解外观模式。1. 实例说明某软件公司欲开发一个可应用于多个软件的文件加密模块,该模块可以对文件中的数据进行加密并将加密之后的数据存储在一个新文件中,...
  • 1、适配器模式(别名为包装器) 考虑这样一种情况,我们要给电脑充电,教室里正好有一个可以充电的插头,但是插头是两孔的,虽然这个插头可以通电,但是我们却没有办法直接用,我们需要一个插板,这个插板是两孔的...
  • 1、职责链模式 很多情况下,在一个软件系统中可以处理某个请求的对象不止一个,比如我们在学校提交请假的申请表,辅导员、系主任、院长和校长都可以处理申请表,他们可以构成一条处理申请表的链式结构,申请表沿着...
  • Java设计模式10——外观模式

    千次阅读 2016-11-05 21:09:44
    外观模式是最简单的设计模式之一,所以我就不再去重写了,简单的总结转载看到的一篇文章,原文链接:http://blog.csdn.net/jason0539/article/details/22775311一、定义外观模式(也称为门面模式)定义了一个高层...
  • 看了很多本关于设计模式的书,大多书都会把这种模式— 外观模式放在第一个位置介绍。 在《设计模式》一书中是这么介绍外观模式的: 为子系统中的一组接口提供一个统一接口...举例说明:原来有一个旧的系统A ,...
  • 外观模式是使用频率最高的结构型设计模式之一,无论是在Web应用软件或是桌面应用软件,还是在移动应用软件中,外观模式都得到了广泛的应用。 外观模式要求外部与一个子系统的通信可以通过一个统一的外观对象进行,...
  • Java设计模式之外观模式 定义:外观模式也称为门面模式,属于结构型模式。外观模式通过定义一个一致性接口,用以屏蔽内部子系统的实现细节,使用端只需跟这个接口发生调用即可实现调用后台的效果。 通俗的讲,就是...
  • 什么是装饰器模式装饰器模式,动态的将责任附加...举例说明我们定义一种饮料,它有描述信息,还有价格,如下public abstract class Drink { String desc = "nothing"; public String getDesc() { return desc; } publ

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,908
精华内容 3,163
关键字:

外观模式的举例说明