首页

什么是ATL? (与COM的关系,及MFC与COM的关系)

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

摘要: 什么是ATL(与COM的关系,及MFC与COM的关系)自从1993年Microsoft首次公布了COM技术以后,Windows平台上的开发模式发生了巨大的变化,以COM为基础的一系列软件组件化技术将Windows编程带入了组件化时代。广大的开发人员在为COM带来的软件组件化趋势欢欣鼓舞的同时,对于COM开发技术的难度和烦琐的细节也感到极其的不便。COM编程一度被视为一种高不可攀的技术,令人望而却步

什么是ATL (与COM的关系,及MFC与COM的关系)
自从1993年Microsoft首次公布了COM技术以后,Windows平台上的开发模式发生了巨大的变化,以COM为基础的一系列软件组件化技术将Windows编程带入了组件化时代。广大的开发人员在为COM带来的软件组件化趋势欢欣鼓舞的同时,对于COM开发技术的难度和烦琐的细节也感到极其的不便。COM编程一度被视为一种高不可攀的技术,令人望而却步。开发人员希望能够有一种方便快捷的COM开发工具,提高开发效率,更好地利用这项技术。
针对这种情况,Microsoft公司在推出COMSDK以后,为简化COM编程,提高开发效率,采取了许多方案,特别是在MFC(MicrosoftFoundationClass)中加入了对COM和OLE的支持。但是随着Internet的发展,分布式的组件技术要求COM组件能够在网络上传输,而又尽量节约宝贵的网络带宽资源。采用MFC开发的COM组件由于种种限制不能很好地满足这种需求,因此Microsoft在1995年又推出了一种全新的COM开发工具ATL。
ATL是ActiveX Template Library的缩写,它是一套C++模板库。使用ATL能够快速地开发出、简洁的代码(Effectiveand Slimcode),同时对COM组件的开发提供最大限度的代码自动生成以及可视化支持。为了方便使用,从MicrosoftVisual C++ 5.0版本开始,Microsoft把ATL集成到VisualC++开发环境中。1998年9月推出的Visual Studio 6.0 集成了ATL3.0版本。目前,ATL已经成为Microsoft标准开发工具中的一个重要成员,日益受到C++开发人员的重视。
ATL究竟给开发人员带来了什么样的益处呢?这还要先从ATL产生以前的COM开发方式说起。
在ATL产生以前,开发COM组件的方法主要有两种:一是使用COMSDK直接开发COM组件,另一种方式是通过MFC提供的COM支持来实现。
直接使用COMSDK开发COM组件是最基本也是最灵活的方式。通过使用Microsoft提供的开发包,我们可以直接编写COM程序。但是,这种开发方式的难度和工作量都很大,一方面,要求开发者对于COM的技术原理具有比较深入的了解(虽然对技术本身的深刻理解对使用任何一种工具都是非常有益的,但对于COM这样一整套复杂的技术而言,在短时间内完全掌握是很难的),另一方面,直接使用COMSDK要求开发人员自己去实现COM应用的每一个细节,完成大量的重复性工作。这样做的结果是,不仅降低了工作效率,同时也使开发人员不得不把许多精力投入到与应用需求本身无关的技术细节中。虽然这种开发方式对于某些特殊的应用很有必要,但这种编程方式并不符合组件化程序设计方法所倡导的可重用性,因此,直接采用COMSDK不是一种理想的开发方式。
使用MFC提供的COM支持开发COM应用可以说在使用COMSDK基础上提高了自动化程度,缩短了开发时间。MFC采用面向对象的方式将COM的基本功能封装在若干MFC的C++类中,开发者通过继承这些类得到COM支持功能。为了使派生类方便地获得COM对象的各种特性,MFC中有许多预定义宏,这些宏的功能主要是实现COM接口的定义和对象的注册等通常在COM对象中要用到的功能。开发者可以使用这些宏来定制COM对象的特性。
另外,在MFC中还提供对Automation 和 ActiveXControl的支持,对于这两个方面,VisualC++也提供了相应的AppWizard和ClassWizard支持,这种可视化的工具更加方便了COM应用的开发。
MFC对COM和OLE的支持确实比手工编写COM程序有了很大的进步。但是MFC对COM的支持是不够完善和彻底的,例如对COM接口定义的IDL语言,MFC并没有任何支持,此外对于近些年来COM和ActiveX技术的新发展MFC也没有提供灵活的支持。这是由MFC设计的基本出发点决定的。MFC被设计成对Windows平台编程开发的面向对象的封装,自然要涉及Windows编程的方方面面,COM作为Windows平台编程开发的一个部分也得到MFC的支持,但是MFC对COM的支持是以其全局目标为出发点的,因此对COM的支持必然要服从其全局目标。从这个方面而言,MFC对COM的支持不能很好的满足开发者的要求。
随着Internet技术的发展,Microsoft将ActiveX技术作为其网络战略的一个重要组成部分大力推广,然而使用MFC开发的ActiveXControl,代码冗余量大(所谓的“肥代码 FatCode”),而且必须要依赖于MFC的运行时刻库才能正确地运行。虽然MFC的运行时刻库只有部分功能与COM有关,但是由于MFC的继承实现的本质,ActiveXControl必须背负运行时刻库这个沉重的包袱。如果采用静态连接MFC运行时刻库的方式,这将使ActiveXControl代码过于庞大,在网络上传输时将占据宝贵的网络带宽资源;如果采用动态连接MFC运行时刻库的方式,这将要求浏览器一方必须具备MFC的运行时刻库支持。总之MFC对COM技术的支持在网络应用的环境下也显得很不灵活。
解决上述COM开发方法中的问题正是ATL的基本目标。
首先ATL的基本目标就是使COM应用开发尽可能地自动化,这个基本目标就决定了ATL只面向COM开发提供支持。目标的明确使ATL对COM技术的支持达到淋漓尽致的地步。对COM开发的任何一个环节和过程,ATL都提供支持,并将与COM开发相关的众多工具集成到一个统一的编程环境中。对于COM/ActiveX的各种应用,ATL也都提供了完善的Wizard支持。所有这些都极大地方便了开发者的使用,使开发者能够把注意力集中在与应用本身相关的逻辑上。
其次,ATL因其采用了特定的基本实现技术,摆脱了大量冗余代码,使用ATL开发出来的COM应用的代码简练,即所谓的“SlimCode”。ATL在实现上尽可能采用优化技术,甚至在其内部提供了所有C/C++开发的程序所必须具有的C启动代码的替代部分。同时ATL产生的代码在运行时不需要依赖于类似MFC程序所需要的庞大的代码模块,包含在最终模块中的功能是用户认为最基本和最必须的。这些措施使采用ATL开发的COM组件(包括ActiveXControl)可以在网络环境下实现应用的分布式组件结构。
第三,ATL的各个版本对Microsoft的基于COM的各种新的组件技术如MTS、ASP等都有很好的支持,ATL对新技术的反应速度大大快于MFC。ATL已经成为Microsoft支持COM应用开发的主要开发工具,因此COM技术方面的新进展在很短的时间内都会在ATL中得到反映。这使开发者使用ATL进行COM编程可以得到直接使用COMSDK编程同样的灵活性和强大的功能。
本文的目的就是希望在有限的篇幅中能够使读者对ATL的使用和基本原理有一个初步的了解,为广大的COM开发人员更好地使用ATL开发起到抛砖引玉的作用。


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


开发中我们需要遵循的几个设计原则!

周周

出处:https://www.cnblogs.com/pengdai


一、开发原则
S:单一职责SRP
O:开放封闭原则OCP
L:里氏替换原则LSP
I:接口隔离法则
D:依赖倒置原则DIP
合成/聚合复用原则
迪米特法则
在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 不管用什么语言做开发,都将对我们系统设计和开发提供指导意义。本文主要将总结这些常见的原则和具体阐述意义。
面向对象的基本原则(solid)是五个,但是在经常被提到的除了这五个之外还有迪米特法则和合成复用原则等,所以在常见的文章中有表示写六大或七大原则的; 除此之外我还将给出一些其它相关书籍和互联网上出现的原则;

二、S单一职责SRP

Single-Responsibility Principle,一个类,最好只做一件事,只有一个引起它的变化。单一职责原则可以看做是低耦合、高内聚在面向对象原则的引申,将职责定义为引起变化的原因,以提高内聚性减少引起变化的原因。

1、定义

一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。(Every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class.),即又定义有且仅有一个原因使类变更。

2、原则分析

一个类或者大到模块,小到方法,承担的职责越多,它被复用的可能性越小,而且如果一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作。
类的职责主要包括两个方面:数据职责和行为职责,数据职责通过其属性来体现,而行为职责通过其方法来体现。
单一职责原则是实现高内聚、低耦合的指导方针,在很多代码重构手法中都能找到它的存在,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。

3、优点

降低类的复杂性,类的职责清晰明确。比如数据职责和行为职责清晰明确;
提高类的可读性和维护性;
变更引起的风险减低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的类有影响,对其他接口无影响,这对系统的扩展性、维护性都有非常大的帮助。
注意:单一职责原则提出了一个编写程序的标准,用“职责”或“变化原因”来衡量接口或类设计得是否合理,但是“职责”和“变化原因”都是没有具体标准的,一个类到底要负责那些职责?这些职责怎么细化?细化后是否都要有一个接口或类?这些都需从实际的情况考虑。因项目而异,因环境而异。

4、例子

SpringMVC中Entity、DAO、Service、Controller、Util等的分离。

三、O开放封闭原则OCP

Open - ClosedPrinciple,OCP对扩展开放,对修改关闭(设计模式的核心原则)

1、定义

一个软件实体(如类、模块和函数)应该对扩展开放,对修改关闭。意思是在一个系统或者模块中,对于扩展是开放的,对于修改是关闭的。一个 好的系统是在不修改源代码的情况下,可以扩展你的功能。而实现开闭原则的关键就是抽象化。

2、原则分析

当软件实体因需求要变化时, 尽量通过扩展已有软件实体,可以提供新的行为,以满足对软件的新的需求,而不是修改已有的代码,使变化中的软件有一定的适应性和灵活性 。已有软件模块,特别是最重要的抽象层模块不能再修改,这使变化中的软件系统有一定的稳定性和延续性。
实现开闭原则的关键就是抽象化 :在"开-闭"原则中,不允许修改的是抽象的类或者接口,允许扩展的是具体的实现类,抽象类和接口在"开-闭"原则中扮演着极其重要的角色..即要预知可能变化的需求.又预见所有可能已知的扩展..所以在这里"抽象化"是关键!
可变性的封闭原则:找到系统的可变因素,将它封装起来。这是对"开-闭"原则最好的实现。不要把你的可变因素放在多个类中,或者散落在程序的各个角落。你应该将可变的因素,封套起来..并且切忌不要把所用的可变因素封套在一起。最好的解决办法是,分块封套你的可变因素!避免超大类、超长类、超长方法的出现!!给你的程序增加艺术气息,将程序艺术化是我们的目标!

3、例子

设计模式中模板方法模式和观察者模式都是开闭原则的极好体现。

四、L里氏替换原则LSP

Liskov Substitution Principle,LSP:任何基类可以出现的地方,子类也可以出现;这一思想表现为对继承机制的约束规范,只有子类能够替换其基类时,才能够保证系统在运行期内识别子类,这是保证继承复用的基础。

1、定义

第一种定义方式相对严格:如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有变化,那么类型S是类型T的子类型。
第二种更容易理解的定义方式:所有引用基类(父类)的地方必须能透明地使用其子类的对象。即子类能够必须能够替换基类能够从出现的地方。子类也能在基类 的基础上新增行为。
里氏代换原则由2008年图灵奖得主、美国第一位计算机科学女博士、麻省理工学院教授BarbaraLiskov和卡内基.梅隆大学Jeannette Wing教授于1994年提出。其原文如下:Let q(x) be a property provableabout objects x of type T. Then q(y) should be true for objects y of type Swhere S is a subtype of T.

2、原则分析

讲的是基类和子类的关系,只有这种关系存在时,里氏代换原则才存在。正方形是长方形是理解里氏代换原则的经典例子。
里氏代换原则可以通俗表述为:在软件中如果能够使用基类对象,那么一定能够使用其子类对象。把基类都替换成它的子类,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类的话,那么它不一定能够使用基类。

里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

五、I接口隔离法则

(Interface Segregation Principle,ISL):客户端不应该依赖那些它不需要的接口。(这个法则与迪米特法则是相通的)

1、定义

客户端不应该依赖那些它不需要的接口。
另一种定义方法:一旦一个接口太大,则需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。
注意,在该定义中的接口指的是所定义的方法。例如外面调用某个类的public方法。这个方法对外就是接口。

2、原则分析:

(1)接口隔离原则是指使用多个专门的接口,而不使用单一的总接口。每一个接口应该承担一种相对独立的角色,不多不少,不干不该干的事,该干的事都要干。
• 一个接口就只代表一个角色,每个角色都有它特定的一个接口,此时这个原则可以叫做“角色隔离原则”。
• 接口仅仅提供客户端需要的行为,即所需的方法,客户端不需要的行为则隐藏起来,应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口。
(2)使用接口隔离原则拆分接口时,首先必须满足单一职责原则,将一组相关的操作定义在一个接口中,且在满足高内聚的前提下,接口中的方法越少越好。
(3)可以在进行系统设计时采用定制服务的方式,即为不同的客户端提供宽窄不同的接口,只提供用户需要的行为,而隐藏用户不需要的行为。

六、D依赖倒置原则DIP

Dependency-Inversion Principle 要依赖抽象,而不要依赖具体的实现, 具体而言就是高层模块不依赖于底层模块,二者共同依赖于抽象。抽象不依赖于具体,具体依赖于抽象。

1、定义

高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。简单的说,依赖倒置原则要求客户端依赖于抽象耦合。原则表述:
(1)抽象不应当依赖于细节;细节应当依赖于抽象;
(2)要针对接口编程,不针对实现编程。

2、原则分析

(1)如果说开闭原则是面向对象设计的目标,依赖倒转原则是到达面向设计"开闭"原则的手段..如果要达到最好的"开闭"原则,就要尽量的遵守依赖倒转原则. 可以说依赖倒转原则是对"抽象化"的最好规范! 我个人感觉,依赖倒转原则也是里氏代换原则的补充..你理解了里氏代换原则,再来理解依赖倒转原则应该是很容易的。
(2)依赖倒转原则的常用实现方式之一是在代码中使用抽象类,而将具体类放在配置文件中。
(3)类之间的耦合:零耦合关系,具体耦合关系,抽象耦合关系。依赖倒转原则要求客户端依赖于抽象耦合,以抽象方式耦合是依赖倒转原则的关键。

3、例子1

理解这个依赖倒置,首先我们需要明白依赖在面向对象设计的概念:
依赖关系(Dependency):是一种使用关系,特定事物的改变有可能会影响到使用该事物的其他事物,在需要表示一个事物使用另一个事物时使用依赖关系。(假设A类的变化引起了B类的变化,则说名B类依赖于A类。)大多数情况下,依赖关系体现在某个类的方法使用另一个类的对象作为参数。在UML中,依赖关系用带箭头的虚线表示,由依赖的一方指向被依赖的一方。
4、例子2
某系统提供一个数据转换模块,可以将来自不同数据源的数据转换成多种格式,如可以转换来自数据库的数据(DatabaseSource)、也可以转换来自文本文件的数据(TextSource),转换后的格式可以是XML文件(XMLTransformer)、也可以是XLS文件(XLSTransformer)等。
由于需求的变化,该系统可能需要增加新的数据源或者新的文件格式,每增加一个新的类型的数据源或者新的类型的文件格式,客户类MainClass都需要修改源代码,以便使用新的类,但违背了开闭原则。现使用依赖倒转原则对其进行重构。
当然根据具体的情况,也可以将AbstractSource注入到AbstractStransformer,依赖注入的方式有以下三种:

[img]https://ss.csdn.net/p?https://mmbiz.qpic.cn/mmbiz_png/ ... rFZQ/640?wx_fmt=png[/img]

七、合成/聚合复用原则

(Composite/Aggregate ReusePrinciple ,CARP):要尽量使用对象组合,而不是继承关系达到软件复用的目的。

1、定义

经常又叫做合成复用原则(Composite ReusePrinciple或CRP),尽量使用对象组合,而不是继承来达到复用的目的。
就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新对象通过向这些对象的委派达到复用已有功能的目的。简而言之,要尽量使用合成/聚合,尽量不要使用继承。

2、原则分析

(1)在面向对象设计中,可以通过两种基本方法在不同的环境中复用已有的设计和实现,即通过组合/聚合关系或通过继承。
继承复用:实现简单,易于扩展。破坏系统的封装性;从基类继承而来的实现是静态的,不可能在运行时发生改变,没有足够的灵活性;只能在有限的环境中使用。(“白箱”复用)
组合/聚合复用:耦合度相对较低,选择性地调用成员对象的操作;可以在运行时动态进行。(“黑箱”复用)
(2)组合/聚合可以使系统更加灵活,类与类之间的耦合度降低,一个类的变化对其他类造成的影响相对较少,因此一般首选使用组合/聚合来实现复用;其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。
(3)此原则和里氏代换原则氏相辅相成的,两者都是具体实现"开-闭"原则的规范。违反这一原则,就无法实现"开-闭"原则,首先我们要明白合成和聚合的概念:
注意:聚合和组合的区别是什么?
合成(组合):表示一个整体与部分的关系,指一个依托整体而存在的关系(整体与部分不可以分开);比如眼睛和嘴对于头来说就是组合关系,没有了头就没有眼睛和嘴,它们是不可分割的。在UML中,组合关系用带实心菱形的直线表示。
聚合:聚合是比合成关系的一种更强的依赖关系,也表示整体与部分的关系(整体与部分可以分开);比如螺丝和汽车玩具的关系,螺丝脱离玩具依然可以用在其它设备之上。在UML中,聚合关系用带空心菱形的直线表示。

八、迪米特法则

(Law of Demeter,LoD:系统中的类,尽量不要与其他类互相作用,减少类之间的耦合度。

1、定义

又叫最少知识原则(Least Knowledge Principle或简写为LKP)几种形式定义:
不要和“陌生人”说话。英文定义为:Don't talk to strangers.
只与你的直接朋友通信。英文定义为:Talk only to your immediate friends.
每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。
简单地说,也就是,一个对象应当对其它对象有尽可能少的了解。一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的public方法,我就调用这么多,其他的一概不关心。

2、法则分析

朋友类:在迪米特法则中,对于一个对象,其朋友包括以下几类:
(1) 当前对象本身(this);
(2) 以参数形式传入到当前对象方法中的对象;
(3) 当前对象的成员对象;
(4) 如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友;
(5) 当前对象所创建的对象。
任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”,否则就是“陌生人”。
3、狭义法则和广义法则:
在狭义的迪米特法则中,如果两个类之间不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
狭义的迪米特法则:可以降低类之间的耦合,但是会在系统中增加大量的小方法并散落在系统的各个角落,它可以使一个系统的局部设计简化,因为每一个局部都不会和远距离的对象有直接的关联,但是也会造成系统的不同模块之间的通信效率降低,使得系统的不同模块之间不容易协调。
广义的迪米特法则:指对对象之间的信息流量、流向以及信息的影响的控制,主要是对信息隐藏的控制。信息的隐藏可以使各个子系统之间脱耦,从而允许它们独立地被开发、优化、使用和修改,同时可以促进软件的复用,由于每一个模块都不依赖于其他模块而存在,因此每一个模块都可以独立地在其他的地方使用。一个系统的规模越大,信息的隐藏就越重要,而信息隐藏的重要性也就越明显。
4、迪米特法则的主要用途:在于控制信息的过载。
在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及;
在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限;
在类的设计上,只要有可能,一个类型应当设计成不变类;
在对其他类的引用上,一个对象对其他对象的引用应当降到。

5、例子

外观模式Facade(结构型)
迪米特法则与设计模式Facade模式、Mediator模式
系统中的类,尽量不要与其他类互相作用,减少类之间的耦合度,因为在你的系统中,扩展的时候,你可能需要修改这些类,而类与类之间的关系,决定了修改的复杂度,相互作用越多,则修改难度就越大,反之,如果相互作用的越小,则修改起来的难度就越小..例如A类依赖B类,则B类依赖C类,当你在修改A类的时候,你要考虑B类是否会受到影响,而B类的影响是否又会影响到C类. 如果此时C类再依赖D类的话,呵呵,我想这样的修改有的受了。

九、Q&A1、面向对象设计其他原则?

封装变化;
少用继承多用组合;
针对接口编程、不针对实现编程;
为交互对象之间的松耦合设计而努力;
类应该对扩展开发、对修改封闭(开闭OCP原则);
依赖抽象,不要依赖于具体类(依赖倒置DIP原则);
密友原则:只和朋友交谈(最少知识原则,迪米特法则);
说明:一个对象应当对其他对象有尽可能少的了解,将方法调用保持在界限内,只调用属于以下范围的方法: 该对象本身(本地方法)对象的组件 被当作方法参数传进来的对象 此方法创建或实例化的任何对象;
别找我(调用我) 我会找你(调用你)(好莱坞原则);
一个类只有一个引起它变化的原因(单一职责SRP原则);

2、你能解释一下里氏替换原则吗?

严格定义:如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象用o1替换o2时,程序P的行为没有变化,那么类型S是类型T的子类型。
通俗表述:所有引用基类(父类)的地方必须能透明地使用其子类的对象。也就是说子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:
  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  • 子类中可以增加自己特有的方法。
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
  • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

3、什么情况下会违反迪米特法则?为什么会有这个问题?

迪米特法则建议“只和朋友说话,不要陌生人说话”,以此来减少类之间的耦合。

4、给我一个符合开闭原则的设计模式的例子?

开闭原则要求你的代码对扩展开放,对修改关闭。这个意思就是说,如果你想增加一个新的功能,你可以很容易的在不改变已测试过的代码的前提下增加新的代码。有好几个设计模式是基于开闭原则的,如策略模式,如果你需要一个新的策略,只需要实现接口,增加配置,不需要改变核心逻辑。一个正在工作的例子是 Collections.sort() 方法,这就是基于策略模式,遵循开闭原则的,你不需为新的对象修改 sort() 方法,你需要做的仅仅是实现你自己的 Comparator 接口。

5、什么时候使用享元模式(蝇量模式)?

享元模式通过共享对象来避免创建太多的对象。为了使用享元模式,你需要确保你的对象是不可变的,这样你才能安全的共享。JDK 中 String 池、Integer 池以及 Long 池都是很好的使用了享元模式的例子。




设计理念如何指导设计落地

鹤鹤

在做项目改版升级时,我们需要做两件大事,一是提炼核心设计理念,二是由理念推动设计执行。



如何从0到1建立设计规范

涛涛


如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里


最近一段时间一直在建立APP的设计规范,从一开始的立项到现在落地上线,可以说是从零开始进行APP全部细节的梳理并且规定规范,这一路走过来还是能总结出很多心得,本文将分为3个部分,阐述如何从0到1建立设计规范。


目录:

一、如何确定内容,规范里要写什么

二、如何写

三、如何推动规范落地


一、如何确定内容?


这里我总结了三步:


Image title



1)确定目标用户、用户目标、设计目标

根据不同的用途和目标,不同的团队对设计规范的制定是不一样。比如为了指导与规范全球第三方开发者进行设计和开发,Google建立的Material Design覆盖面广,每个组件细节写得非常细致。Ant Design则是直接做出了组件,方便直接进行调用。有些国内设计团队的规范则是主要描述常用控件和色值。因此我们需要确立用户目标和设计目标,这样才能确定我们的规范侧重点是什么,需要做成怎么样的形式。


在这里我列举了自己撰写规范时的用户与目标:


Image title



2)模范大平台,先列全

一个规范里面的东西是很多的,那么我们究竟需要做什么呢?假如一开始我们没有方向,找一个,列一个,这样我们很容易疏漏很多情况。在这里我采用的的一个办法是:首先熟读iOS,Material Design规范,并且模范他们,在脑图中,把规范中应含有的所有内容罗列出来,罗列一个大纲。


这里我列举当时自己做的一个脑图大纲,覆盖了主流规范中的所有细节,大家可以进行参考并模仿:

Image title



3)针对自己情况进行删减

列完齐全的大纲后,我们需回顾设计目标,对大纲里的内容进行删减。(比如在组件、模式这些地方,可以对着自己的APP,进行挨个寻找,看自己的APP当前是不是运用了这个组件,没有的话就进行删减。)


在这里我列举了针对自身APP的情况删减后的大纲图:

Image title

二、如何写

进过了以上的三步,我们基本得出了要写什么的框架了,接下来就是如何写规范的阶段。


这里我总结了3步:

Image title


1)确定优先级

我们可以通过版本迭代计划+性价比+重要性(该组件在页面出现的场景次数以及当前的不统一对APP体验影响程度)这几个维度分别确定每块内容的优先级和分工。基础的、必要的、高性价比的放在第一期,复杂的向后放,随着产品的迭代,我们的规范也会越来越完整。


同时需要留意版本规划,了解即将要做的功能或即将要改版的页面。我们可以提高这里面牵涉到的控件、组件等内容的优先级。庞大复杂,牵涉到很多页面的,我们可以先降低其优先级:比如全局提示框的规范,toast的规范。


同时,我们也需常与开发沟通,争取把可复用性高、组件日后变化幅度少的组件做成开发组件库。


2)确定规范书写格式

我们制定的规范本身也是设计的交付物,假如每个设计师都按照自己的喜好来编写规范,那么这个规范本身也会变得不规范,规范自身保持一致性是提高规范阅读效率的一部分。


我们可以回归我们之前制定的用户目标和设计目标来制定我们规范的书写格式。规范的用户群是谁,主要想达到什么作用,是通过文档展示还是网上展示,确定了这些问题后,就可确定规范的详细程度、主要的展示形式(比如前文说到的Ant Design和Material Design)。


这里我的思考点是:假如规范写太多字就会变得很臃肿,没有人喜欢慢慢仔细的阅读你写的规范,所以我们应该做到写得简明扼要,再辅以例子说明(根据开发的习惯,都是喜欢直接看例子,看标注)。


我的书写格式是:先写描述这个组件是什么,再列举出现的场景,然后编写交互规则,最后给出视觉标注+例子。


3)逐步对单个规范进行整理与书写

当确定了要写什么东西和格式之后,我们开始进入到细节,对每个内容进行整理,制定规范了。


通过对每个内容制定规范规范也是有方法的:


Image title


下面我通过整理“列表”这个规范来讲解:


1.收集出现的所有的场景。

当一个产品已经趋于成熟,这个组件出现的场景就会非常多,比如对话框,toast,列表这些组件出现的地方很多,需要我们自己仔细地体验产品,把所有页面都找出来。


2.提取共性,归纳分类

我们需要分析每个页面的特点并且把相同特点的页面归纳一起,众多的页面场景就能整理成几个典型的种类,然后只需对这几个典型的种类进行定义和描述即可。

在列表中,我分为了大封面列表、小封面列表、用户列表、单行列表


3.编写规则

在分类好后,我们可以对每个种类编写规则,在这里我们需要描述好每个种类有什么特点或属性,什么时候场景下适用,并且给出标注和例子,方便阅读者理解。


4.多与组内成员讨论修改

在制定好初稿后,我们可以与组内成员宣讲下自己制定的规范。多从别人的角度出来,确保你编写的规范是否易懂,是否包含了全部的情况,是否容易执行落实。


三、如何推动规范落地

写完内容后,最重要的一步就是推动落地,规范要真正有人用才能体现价值,在这里我给出几点帮助推动规范落地的小建议:

1.制定规范推进进度表

表格里面应该包含规范制定的优先级,分工进度,分工人员,并且确定每一期进度的交付时间,开会讨论的时间,作为负责人,也可以适时提醒成员每次的开会时间(毕竟deadline是第一生产力)。


2.编写过程中多与其他成员讨论,达成一致性共识

制定规范后,与部门其他人员进行宣讲,灌输概念,针对如何更好的落实进行讨论调整。在设计中都不可能一次就完美,我们需要不断的在修改中逐渐完善。


3.规范建成后放在网上

同步在网上,方便部门内的其他成员能随时查看和团队成员对规范的更新修改、同步。


4.强制性制定规则要求团队成员执行

有明确的惩罚机制和要求才能更好的执行,不然在规范制定后很容易健忘此事。(我们组的惩罚机制就是罚钱)。


5.规范保持持续的更新迭代

规范推动落地后并不是完全了事,要根据产品的迭代,保持规范的更新。

这整个制定规范的项目中,还是有不少反思的地方,值得我们深思和注意:


1.切记不要为设计规范而做规范

规范最重要的点是能推动落地,能确确实实改善产品,达到统一性。因此我们在设计规范时,并不需要“高大上”术语,给出一大堆的设计理念用来提升设计逼格。而是真正的回归到我们的设计目标,针对目标用户制定规范,做到简朴、易懂、能落地。

2.没人愿意阅读长篇文字

我们应该尽量控制文案长度,做到通俗易懂即可。

3.要时刻围绕我们的目标做规范

比如,我这次做的规范中有一项是去工具化,在制定控件中,空白页面中就会加入很多趣味化的设计。


4.灵活变通

规范只是适合大多时候的场景,对于一些规范中没有包含或者不符合规范的场景,我们可以灵活变通,积极创新或者是补充新的规范(前提是与组内积极沟通,达成共识)。


总结:

再来回顾如何从0到1建立规范


一、确定内容

1.确定用户目标和设计目标

2.模仿大平台,列全

3.针对自己情况进行缩减


二、写

1.确定优先级

2.确定规范书写格式

3.逐步对单个内容进行整理与书写:a.收集全部情况 b.分类归纳 c.提取共性,编写规则

三、推动

1.制定规范推进进度表

2.编写过程中多与其他成员讨论

3.把规范建成后放在网上

4.强制性制定规则要求团队成员执行

5.规范保持持续的更新迭代


今天分享的内容就是这些了,希望能帮助到大家,感谢阅读~



蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务


《魔力物语》UI界面变革,新旧UI对比

蓝蓝设计的小编

经过一个多月的闭关潜修,新MMORPG回合制游戏《魔力物语》近期又准备和大家见面了。至于具体的开测日期,容小编先卖个关子(PS:我绝对不会说其实我也不知道)。在上次结束之后,我们针对测试出现的问题进行修复并优化游戏。在一个多月的优化中,游戏将会脱胎换骨,以更完善的姿态和大家见面。下面就让大家看下游戏UI界面优化的成果。

CSS隐藏元素的五种方法

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

用css隐藏页面元素有许多种方法。

  1. 1、opacity:0
  2. 2、visibility:hidden
  3. 3、diaplay:none
  4. 4、position:absolute

opacity

     opacity属性的意思是设置一个元素的透明度。它不是为改变元素的边界框(bounding box)而设计的。这一位着将opacity设置为0只能从视觉上隐藏元素。而元素本身依然占据它自己的位置并对网页的布局起作用,它也将响应用户交互。


visibility

     第二个要说的属性是visibility。将它的值设为hidden将隐藏我们的元素。如同opacity属性,被隐藏的元素依然会对我们的网页布局起作用。与opacity唯一不同的是它不会响应任何用户交互。此外元素在读屏软件中会被隐藏

    注意,如果一个元素的visibility被设置为hidden,同时想要显示它的某个子孙元素,只要将那个元素的visibility显式设置为visible即可。

    

dispaly

    display属性依照词义真正隐藏元素。将display属性设为none确保元素不可见并且连盒模型也不生成。使用这个属性,被隐藏的元素不占据任何空间。不仅如此,一旦display设为none任何对该元素直接打用户交互操作都不可能生效。此外,读屏软件也不会读到元素的内容。这种方式产生的效果就像元素完全不存在。

    任何这个元素的子孙元素也会被同时隐藏。为这个属性添加过度动画是无效的,他的任何不同状态值之间的切换总是会立即生效。

    不过请注意,通过DOM依然可以访问到这个元素。因此你可以通过DOM来操作它。


position

    假设有一个元素你想要与它交互,但是你又不想让它影响你的网页布局,没有合适的属性可以处理这种情况(opacity和visibility影响布局mdisplay不影响布局但又无法直接交互)。在这种情况下,只能考虑将元素移出可视区域。这个办法既不会影响布局,有可能让元素保持可以操作。

  1. .hide {
  2. position: absolute;
  3. top: -9999px;
  4. left: -9999px;
  5. }


clip-path

    隐藏元素的另一种方法是通过剪裁它们实现。

  1. .hide {
  2. clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px);
  3. }

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


jQuery-瀑布流【CSS】CSS隐藏元素的五种方法

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

用css隐藏页面元素有许多种方法。

  1. 1、opacity:0
  2. 2、visibility:hidden
  3. 3、diaplay:none
  4. 4、position:absolute

opacity

     opacity属性的意思是设置一个元素的透明度。它不是为改变元素的边界框(bounding box)而设计的。这一位着将opacity设置为0只能从视觉上隐藏元素。而元素本身依然占据它自己的位置并对网页的布局起作用,它也将响应用户交互。


visibility

     第二个要说的属性是visibility。将它的值设为hidden将隐藏我们的元素。如同opacity属性,被隐藏的元素依然会对我们的网页布局起作用。与opacity唯一不同的是它不会响应任何用户交互。此外元素在读屏软件中会被隐藏

    注意,如果一个元素的visibility被设置为hidden,同时想要显示它的某个子孙元素,只要将那个元素的visibility显式设置为visible即可。

    

dispaly

    display属性依照词义真正隐藏元素。将display属性设为none确保元素不可见并且连盒模型也不生成。使用这个属性,被隐藏的元素不占据任何空间。不仅如此,一旦display设为none任何对该元素直接打用户交互操作都不可能生效。此外,读屏软件也不会读到元素的内容。这种方式产生的效果就像元素完全不存在。

    任何这个元素的子孙元素也会被同时隐藏。为这个属性添加过度动画是无效的,他的任何不同状态值之间的切换总是会立即生效。

    不过请注意,通过DOM依然可以访问到这个元素。因此你可以通过DOM来操作它。


position

    假设有一个元素你想要与它交互,但是你又不想让它影响你的网页布局,没有合适的属性可以处理这种情况(opacity和visibility影响布局mdisplay不影响布局但又无法直接交互)。在这种情况下,只能考虑将元素移出可视区域。这个办法既不会影响布局,有可能让元素保持可以操作。

  1. .hide {
  2. position: absolute;
  3. top: -9999px;
  4. left: -9999px;
  5. }


clip-path

    隐藏元素的另一种方法是通过剪裁它们实现。

  1. .hide {
  2. clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px);
  3. }

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


谈谈移动端布局

周周

移动端推广速度快,效果好,越来越多的企业,商家开始重视移动站的建设和移动页面(h5)的制作。随着移动页面的玩法越来越多,对前端技术的要求也会越来越高。

选择合适的布局,是写好移动页面的第一步。今天我们就来谈谈移动端的布局问题。
为什么移动端布局如此混乱?这是由多方的原因造成的。
1. css这套技术系统本身十分混乱,基本上可以说毫无规律可言,依赖于技术人员的熟练程度而不是逻辑更多一些;
2.css历经了多个时代的升级,每一次升级之后,新的技术标准和旧的基本上没有任何关联。比如:table布局,div+css布局,flex布局,grid布局等;
3. 手机终端市场的混乱。当前市场上手机的尺寸五花八门;加上由iphone的retina技术带来的dpr的混乱;

关于移动设备一些基本概念的理解。



一. 物理设备像素。
思考:为什么手电筒只能发出一种颜色的光,而我们的屏幕能发出这么多种颜色的光?
因为我们的屏幕是由无数个小的手电筒组成的,每个点可以发不同颜色的光,最后就组成了我们看到的彩色的效果。
每张图片都是由色点组成的,每个色点称为一个像素。一张图片由30万个色点组成,这个图片的像素就是30W。我们常说相机是多少像素,这个像素实际就是在说这款照相机的感器件有多少个,有100W个感光器件的相机就是100W像素的相机,有4000W个感光器件的相机就是4000W像素,以此类推。一台100W像素的相机拍摄的照片洗成5寸的照片会比洗成6寸清晰一点。
二. 屏幕分辨率
屏幕分辨率是屏幕每行的像素点数*每列的像素点数,每个屏幕有自己的分辨率。屏幕分辨率越高,所呈现的色彩越多,清晰度越高。
结论:
1. 像素的单位本质上是:个数,100像素你可以理解成你有100个手电筒;
2. 同样大小(比如1cm*1cm大小的矩形),里面的像素越多,画面越清晰;
三.css像素
在pc端1css像素相当于1物理设备像素。
思考:
我们的手机分辨率是640*1136(iphone 5和iphone 5s的物理设备分辨率),如果我们打开一个纯粹pc端的网站会出现什么情况?
(比如jumei.com,min-width是1090px,在pc端的我的电脑的设备宽度是1280,通过screen.width进行检测)
我们会发现网站会缩小到我们可以看到整个网站(www.jubi.com)
则会发现,有滚动条了,因为禁止缩放了
四. dpr
1个css像素占多少物理设备像素
思考:iphone 5或者iphone 5s一屏幕能看到的极限是多少宽度?
应该是320(这是默认的可视区的css宽度) * 2 = 640px
以上,我们学习完了所有关于移动端布局相关的概念,接下来,我们来聊一聊布局的思路。
假如我们有640px的设计稿,我们如何才能让用户全部看到呢?
思路一:百分比布局
把尺寸除以2,比如我们量出来的是640px ---> 实际上我们只写320px;
如果是iphone 6怎么办? iphone 6的宽度是375px;
由于320和375的宽度其实差别不大,我们可以不定宽度,也就是把整体宽度设定为100%,然后其他的全部量出来是多少。
布局方法
- 拿到设计师给我们的设计稿之后(推荐640px),把所有量出来的尺寸除以2即可
- 遇到等分就用百分比
- 左浮动 + 右浮动(导航部分实现、折扣推荐导航部分) --> 适合于所有的元素宽度固定的
- 左浮动 + padding挤(见超值折扣推荐内容部分) 本质上元素大小在任何尺寸下面都是一致,改变的其实是元素与元素之间的间距大小 --> 适合一个元素宽度固定,另一个宽度自适应;

网站示例

http://m.duba.com/

http://m.lagou.com/

百分比布局的缺点
在大屏幕的手机下显示效果会变成有些页面元素宽度被拉的很长,但是高度还是和原来一样,实际显示非常的不协调,这就是流式布局的最致命的缺点,往往只有几个尺寸的手机下看到的效果是令人满意的,其实很多视觉设计师应该无法接受这种效果,因为他们的设计图在大屏幕手机下看到的效果相当于是被横向拉长来一样。流式布局并不是最理想的实现方式,通过大量的百分比布局,会经常出现许多兼容性的问题,还有就是对设计有很多的限制,因为他们在设计之初就需要考虑流式布局对元素造成的影响,只能设计横向拉伸的元素布局,设计的时候存在很多局限性。
思路二:rem布局
如何理解rem布局?
思考一个问题,假如我们的设计稿是750px,我们量出来一个盒子的宽度是75px,那么在640px下面,它应该是多少合适呢? 答案是:64
问题,如果才能保证你写的css的尺寸只需要写一次,在不同的屏幕尺寸下面不用改?
假如我们在750px下面,我们让html的font-size为75,则这个盒子的宽度是1rem,在640px下面我们让html的font-size为64,则这个盒子的宽度也是1rem,问题就这样解决了。
那么实际开发中,该用什么样等布局思路?
我们打开m.jd.com,m.vip.com,会发现,实际上没有一个网站用了纯粹的百分比或者rem布局,经常会发现各种布局思路混在一起,因为没有一套布局思路能够通用保证不出问题
为什么rem不是万能的?
比如1px,如果我们在dpr是2的情况下就会变得很粗,我们知道那并不是真正的1像素。
推荐布局思路——使用由阿里出品的lib-flexible库。

网址:https://github.com/amfe/lib-flexible


该如何使用呢?
1. 引入布局用的flexible.js要注意的是不要再写meta:viewport标签了,因为flexible.js会自动帮你创建;
2. 引入base.css;
3. 把设计师的设计稿拿过来,标注稿基准字体大小 = 标注稿宽度 / 10,如标注稿宽为750,标注稿基准字体大小为75;标注稿宽为640,标注稿基准字体大小为64;
4. 除了字体大小以外,其他所有的均按rem来,比如你的设计稿是750px的,那么,假如你量出来的是75px,则是1rem;
字体除外,要根据不同的dpr设置不同的大小,比如如果是750的设计稿,那么字体假如是24px,则在dpr为1的情况下是16px,dpr2的情况下是24px,dpr3的情况下是32px(这块涉及到字体专业知识,总结一句话就是没有人会考虑用奇数字体,https://www.zhihu.com/question/20440679,所以不能让工具帮我们自动算,得写死。
以上是我个人关于移动端布局的一些总结。如有不妥的地方,还请指正。
最后附上关于移动端常见问题当网址:



用Airbnb 的产品,帮你快速理解尼尔森10大可用性原则!

涛涛

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

本文聚焦 Airbnb 产品,描述10大可用性原则的应用场景,希望能够帮助你更系统地理解10大可用性原则。

一、系统状态的可见性

Visibility of system status

The system should always keep users informed about what is going on, through appropriate feedback within reasonable time.——Nielson

系统应该在合理的时间内通过适当的反馈,始终让用户了解正在发生的事情。

这项原则通常被遵循并使用在如下几个场景:

  • 系统导航、Toast。让用户明确知道「我在哪」;
  • 按钮、图片等元素可被交互的表达与反馈。通过视觉、与空间上的反馈,向用户传达页面元素是可以被交互的,引导用户前往下一站;
  • 用户完成交互动作和系统操作后,系统需要给予用户对应的反馈。比如操作成功、完成注册等;

Airbnb 的房源详情页顶部导航,可以通过点击快速定位到房源的某类信息,让用户清晰地知道「我在哪?我还能去哪?」

在发布房源时,系统顶部模拟了进度条,显示出了当前步骤,以及当前的发布进度。

二、贴近用户的真实环境

Match between system and the real world

The system should speak the users’ language, with words, phrases and concepts familiar to the user, rather than system-oriented terms. Follow real-world conventions, making information appear in a natural and logical order.——Nielson

系统应该说用户的语言,用户熟悉的单词,短语和概念,而不是系统导向的术语。遵循现实世界的约定,使信息以自然和合乎逻辑的顺序出现。

这项原则说的直白一些,就是:「说人话」。

产品简单到傻瓜也能操作,是乔布斯和张小龙做产品的核心理念。坐拥10亿用户的微信之父张小龙说过,做产品要有傻瓜心态。不要炫耀自己的智商,不要让用户觉得自己是白痴,请用最简单直白的语言描述状况;就好比自然世界里,你和他人说话的时候必然使用简单的白话文进行直白的沟通以保证交流顺畅。

在房源的详情页、Airbnb PLUS 介绍页,系统用了大量高质量的摄影图片传达一种空间氛围感。同时,在介绍文案的措辞方面,简洁易懂,语言逻辑清晰。

三、用户有控制和来去自由的权利

User control and freedom

Users often choose system functions by mistake and will need a clearly marked 「emergency exit」 to leave the unwanted state without having to go through an extended dialogue. Support undo and redo.——Nielson

用户通常会错误地选择了系统的某个功能,并且需要一个明确标记的」紧急出口「来离开不想要的状态,而不必进行扩展对话。支持撤消和重做。

用户拥有自由使用和控制系统的权利,最为常见的就是系统会为用户提供「撤销、重做、返回」的入口。

在故事专栏,当用户在浏览器当前标签页进入下一级页面时,系统都为用户提供了返回按钮,一方面方便用户来去自由,另一方营造出了一定的沉浸式浏览体验。

四、系统的一致性

Consistency and standards

Users should not have to wonder whether different words, situations, or actions mean the same thing. Follow platform conventions.——Nielson

用户不应该怀疑不同的话语、情况或行为是否在表达同样的一件事情。系统设计需遵循平台惯例。

  • 移动端 APP 内的返回按钮位置通常会被放在左上角,当然有些 APP 会将返回按钮统一放在左下角,虽然返回按钮的位置不同于大多数 APP,但对于此 APP 的返回交互来说,其实还是一致的;
  • 除常用按钮位置需要符合一致性原则外,icon 的视觉设计也要遵循一致性原则,一个对象对应一个 icon.

在房源、故事集列表页,系统统一用了卡片式的视觉风格,并且每个卡片里的文字与背景图片的层次也都保持一致。

在房源详情页,系统使用了统一的 iocn 风格和文字风格,传达房源的设施属性。

五、防止错误

Error prevention

Even better than good error messages is a careful design which prevents a problem from occurring in the first place. Either eliminate error-prone conditions or check for them and present users with a confirmation option before they commit to the action.——Nielson

比良好的错误提示信息更好的方法是:一个走心的设计可以提前防止错误的发生。系统要么消除容易出错的情况,要么检查它们,并在用户采取行动之前向用户提供确认选项。

  • 比如某些操作不能进行,那就置灰或隐藏,不要在用户点击后才提醒不能操作。如果有某些内容不能选择,就置灰或者隐藏,不要等用户点击完成时才告知不能使用;
  • 同样,在用户容易出现错误操作的场景下,需要给出二次确认,如:删除和取消重要信息的操作。

如果房源在某天或多天已被预定或暂时不开放,则日历里将这些不可预定的日期置灰。

用户在修改个人重要信息后,系统会让用户输入密码二次确认。

六、系统识别胜过用户记忆

Recognition rather than recall

Minimize the user’s memory load by making objects, actions, and options visible. The user should not have to remember information from one part of the dialogue to another. Instructions for use of the system should be visible or easily retrievable whenever appropriate.——Nielson

通过使用对象,动作和选项的可视化表达,最大限度地减轻用户的记忆负担。用户不应该记住从对话的一部分到另一部分的信息。

  • 为用户保留查看和搜索历史是一个很常见的系统识别的例子;
  • 用户在填写一个长页面表单时,系统可以根据实际情况提供一个实时预览的功能,避免出现用户填了下面忘了上面的情况;
  • 用户在填写完表单(比如订单页面)后,系统可以再次向用户展示所填信息,以最终确认;
  • 用户为了完成一项目标任务,从一个页面跳转到另一个页面后,系统可以再次展示上一个页面内与目标任务相关的核心信息,以减轻用户的记忆负担。

系统会在首页第一屏为用户展示浏览历史(登录后)。

搜索框也会保留最近5次的搜索历史。

七、灵活易用的使用体验

Flexibility and efficiency of use

Accelerators — unseen by the novice user — may often speed up the interaction for the expert user such that the system can cater to both inexperienced and experienced users. Allow users to tailor frequent actions.——Nielson

一些被精心设计的体验也许会被专家用户察觉到,使系统需要能够满足无经验和有经验的用户。允许用户进行频繁的操作。

当用户在滚动屏幕浏览房源详细信息时,系统将预定的基本信息(如:价格、日期、人数等)固定在浏览器的右侧,方便用户在浏览过程中随时开始预定步骤。

八、美观和简约的设计

Aesthetic and minimalist design

Dialogues should not contain information which is irrelevant or rarely needed. Every extra unit of information in a dialogue competes with the relevant units of information and diminishes their relative visibility.——Nielson

对话中不应该包含无关紧要或很少需要的信息。在对话中每增加一个相对重要的信息,就意味着需要弱化其他信息。

高颜值不需要理由。

九、帮助用户识别,诊断,并从错误中恢复

Help users recognize, diagnose,and recover from errors

Error messages should be expressed in plain language (no codes), precisely indicate the problem, and constructively suggest a solution.——Nielson

错误信息应该用通俗易懂的语言表达(不要用代码),较准确的反应问题,并且提出解决方案。

实在无法避免的报错时,不要单纯只是报错,要提供解决方案。就好比小时候犯错,你绝不能光说:「啊,我错了。」老师或家长必然会追问:「错哪儿啦?」你要是说不出缘由,则必定被认为认错不诚恳不真心。

当用户填写错误时,系统会及时给出提示以及解决方法。

十、帮助文档

Help and documentation

Even though it is better if the system can be used without documentation, it may be necessary to provide help and documentation. Any such information should be easy to search, focused on the user’s task, list concrete steps to be carried out, and not be too large.——Nielson

如果系统能让用户不需要阅读文档就会使用那是最好的,但通常情况下还是需要帮助文档的。任何信息应该容易被搜索,且专注于用户的目标任务,并列出具体的步骤来告知用户。

  • 对于一些可以用一句话说清楚的帮助,可以直接在对象旁边提供鼠标悬停出发的 tips,或者简明的辅助说明;
  • 对于较复杂的,一两句话说不清楚的帮助,则需要跳转至对应的帮助页面;
  • 系统需要有一个帮助中心,为用户提供模糊搜索、分类搜索,来为用户提供更全面的帮助。

在个人资料页面,对于用户关心的隐私信息,系统会给出非常有亲和力的解释文案。此外,在系统很多页面都有对应功能的帮助链接以跳转至帮助中心。

系统的帮助中心,提供了搜索和问题分类引导,方便用户快速定位问题。

△ 本文图片版权归 Airbnb 所有

总结

号称以设计驱动的 Airbnb 公司,的确在产品设计、用户研究、UX设计方面展现出了较高的功力。网站甚至移动端APP 的框架层、范围层、视觉层的设计都体现出了高度的用户体验一致性和品牌感。可以看出,Airbnb 对 design system 的重视一级高度的执行力。什么是好的产品品牌认知和识别,我可以简单的理解为:「脱掉」Logo,用户照样认识你。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务

掉进这6个陷阱,可能会毁了你的原型设计!

涛涛


如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里


很难想象,如果没有原型设计,如今的数字产品设计流程会变成什么样。原型的存在,让产品团队在制作和开发过程中更加直观,就像那句话说的:展示,而非表述。

现如今,许多产品团队借助原型来测试想法,甚至销售产品。不过,原型设计本身并非是万无一失的,设计师依然会面临许多陷阱,并且拖累整个产品的进程。

今天的文章,总结了6个常见的原型设计的陷阱。

1. 目标不明确的原型设计

我们先设计出来,然后弄明白如何使用它。

在这种说法的指引下,设计和开发团队需要花费大量的时间来处理那些没有任何价值的事务,在没有特定目标的情况下制作原型,会浪费大量的时间。

每个原型的设计目标应该是非常明确的,原因应该是清晰的。这个目标可以是源自于一个特定的想法,或者某种假设,产品团队在这个方向的指引之下,利用系统化的知识来构建符合目标的原型。

在创建原型之前,设计师应该问自己一个问题,「通过创建这个原型我们要试图解决什么问题?」如果能够找到一个明确的答案,那么这个原型是清晰且具有凝聚力的,有助于减少潜在的开销。

2. 制作原型过程受阻

产品团队通常会力图制作出有效有用的原型。当制作出来的原型不可用甚至根本无法完成的时候,整个团队会为之气馁,而这种消极的心态可能会拖垮整个项目。

为了提率,设计人员应当将失败的情况视作为整个原型制作过程中自然的组成部分。原型在很多时候是用来测试假设和想法的,并非每个假设都是有效的。这就是为什么创建工作原型不应该是原型制作工作最重要的结果。原型制作工作最重要的成果应该是获取有用的信息和新的知识。因此,将焦点从失败的情绪上,转移到学习新的知识上来,成功和失败的原型,都能够让你的产品进步。就像大家常说的,失败是成功之母。

3. 对第一个想法精雕细琢

产品团队常常在拥有第一个想法的时候,就想坚持住,将它打磨成为最终的解决方案。随后,团队花费大量的时间来出揣摩尝试,调整细节,制作原型,甚至直接开始设计视觉稿。

结果,花费无数小时创建和打磨的原型,在可用性测试早期,就呈现出不理想的状况,接下来,设计师和团队会意识到最初的想法其实不够好。

经验丰富的团队知道,想要探索和测试一系列的想法是必不可少的,并且只有通过测试之后,效果最好的方案,才是值得坚持做下去的。花费更多的时间来思考,团队才能针对问题空间继续挖掘下去,并且找到潜在的解决方案。

4. 爱上你的原型

原型的设计者常常会对于自己的设计有大量的投入。这种投入是会造成一种「投资偏见」——你在某个事情上花费的时间越多,它对你来说就越有价值。值得注意的是,它对于你的价值会越来越高,但是对于别人而言并非如此。而原型设计同样如此,当设计师对于自己的原型过度沉迷的时候,产品可能就会暴露在危险之下了:你会很容易忽略它们存在的缺点,即使这些缺陷很明显,设计师也会忽略团队成员和其他人的反馈。

不要拿原型当传家宝。

在打磨原型上花费太多宝贵的时间和精力,会剥夺设计师对于反馈应有的注意力和敏锐度。让你的原型在细节和复杂度上保持在一个合理的度上。

原型并不是艺术品,它应该是帮你找到答案的工具。

如果你倾向于采用尽可能完善的设计,那么请采用最小可行原型——添加足够的细节,但是尽可能确保可行。将原型视作为一次性的工具。每个原型都有特定的用途,一旦达到目标,就尽可能用更好的东西替换它。

5. 忽略草图的重要性

「当我们拥有强大的原型工具的时候,为什么还要使用纸和笔呢?」设计师跳过手绘阶段,并且直接使用计算机来绘制数字原型的时候,他们相信数字化的设计是可以节省时间的。但是实际上,手绘的草图能够帮助设计更快地起步。

当你下次不知道如何解决问题的时候,可以试着从笔和纸开始绘制草图。只需要开始绘制草图,勾勒出所能想到的变化,然后把它们贴在墙上,并且和你的团队一起从技术和业务的角度上讨论可行性。

6. 为原型选择错误的保真度

保真度是描述细节程度的一种度量,我们常说的线框图细节简略,是低保真的,而视觉稿则常常会用到丰富的细节刻画,它是高保真的。原型的呈现形态是非常多样的,可以是低保真的也可以是高保真的。制作一个高保真的原型是非常诱人的,但是一定要抵制住这样的诱惑。值得注意的是,原型的保真度应该和你想法的保真度相匹配。

这意味着,设计师应该根据他们的设计过程所处的阶段来选择保真度。当设计师违反这一规则的时候,往往会带来糟糕的结果。比如过高的保真度会让处于早期阶段的设计师陷入「投资偏见」。

当团队设计产品尚且处于初期的时候,尽量采用低保真的策略来进行绘制,比如使用草图。

△ 低保真的草图原型

当你想要与真实的用户一起测试你的想法的时候,尽量使用保真度更高的设计,比如数字化的可交互的原型。使用高保真的原型来进行可用性测试,能够产生更真实、具体的反馈。高保真的原型展示给利益相关者来看也非常有用,他们会更好地判断产品的功能和内容。

△ 在 Adobe XD 中创建高保真的原型

因此,考虑最终的目标和你所拥有的时间,来确保原型的最佳保真度,尽早与期望达成一致。

结语

原型设计在每个产品设计项目当中都是至关重要的,正确地设计原型,才能尽早地构建真实的产品。

One more thing

关于原型设计,乔布斯在1992年 MIT 的演讲上说到的一个事情非常有意思。彼时,他还未回归苹果,而是在制造名为 NeXT 的高端电脑,并且对于面向对象编程有着极高的热忱。

我们已经有2年时间没有构建任何工程上的原型了。这意味着,从产品开始设计的第一天,工程师和整个制造业就已经参与进来了。很多时候,在构造原型的时候,生产工具和技术根本是无法与之匹配的,而当你在原型设计的时候所积累的东西,在投产的时候就得完全抛弃,然后重新开始。因为我们始终紧密地和技术结合起来做,因此我们不会抛弃任何东西,并且不浪费时间,这也是我所见过的设计、工程和制造团队之间,最健康的关系之一。

现如今,身为设计师的我们在使用 Photoshop、InVision 等工具制造原型的时候,实际上开发可能是与之脱节的。产品团队中,设计和开发之间的矛盾,从来没有仅此减少过。而「全栈设计师」这一概念的提出,又何尝没有来自这种矛盾的压力呢?

诸如 Sketch 和 Figma 这样的新工具在做原型设计的时候,已经或多或少地开始在设计和开发之间找到协同的点,试图在设计验证和技术验证之间,找到结合的办法。

更好的原型设计,更合理的技术和设计的结合点,这也许是我们未来的探索方向吧。


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计  cs界面设计  ipad界面设计  包装设计  图标定制  用户体验 、交互设计、 网站建设 平面设计服务


日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档