白话设计模式

创建型设计模式

对象怎么来 提供一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。

工厂方法

重点在于Factory类,当一个类的实例化依赖于不同场景时需要使用的,比如根据形状不同实例化不同形状类并返回的demo,根据不同的形状,实例化的Shape对象内部的实现逻辑不一样,这时候就可以使用工厂方法模式,将类内部的实现细节隐藏起来,用户只需要告诉工厂类自己需要什么情况下的产品,工厂就可以自动调用自己内部对应场景的代码从而返回一个用户需要的“产品”。

抽象工厂

抽象工厂可以理解为工厂的工厂,比如demo中,首先有两个工厂Factory,分别用来实例化不同场景下的shape和color,然后再有过一个工厂的工厂即FactoryProducer,其根据用户的需求(shape或者color)返回shape工厂或者color工厂,然后用户再用返回的工厂去实例化自己需要的shape或者color。
对比工厂方法模式,因为一个工厂只能生产一个产品,比如一个ShapeFactory只能根据不同情况实例化一个不同的Shape,那么当我们需要一整套的产品(比如形状和颜色形成了一套产品)时使用工厂方法显然就不能解决了,所以就需要抽象工厂模式,抽象工厂模式实际上是工厂的工厂,即其作用的目的是为了实例化不同的工厂,用户再通过不同的工厂实例化不同场景下成套的产品。

单例模式

通俗来讲就是替用户实现对象的实例化,用户需要使用类的时候不需要实例化,直接通过getInstance就可以拿到需要使用的对象,进而调用对象的方法即可,这个设计模式平时用到的比较多,也比较容易理解。

生成器(建造者)模式

生成器模式的目的是使用多个简单的对象一步一步构建成一个复杂的对象,比如在一个快餐店的商业案例中,一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡(Burger)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中。冷饮(Cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。 那么,生成器(MealBuilder)的作用就是实现不同类型汉堡(Burger)与不同类型冷饮(Cold drink)的搭配,即通过MealBuilder这个生成器可以通过组合不同汉堡和冷饮这样简单的类从而狗仔出一个复杂的套餐(Meal)类,这就体现了生成器模式“使用多个简单的对象一步一步构建成一个复杂的对象”的要点,需要注意的是建造者模式与工厂方法模式有类似的地方,但是建造者模式更加关注零件装配的顺序而且生成的对象内部属性本身具有相互依赖性,比如Demo中的食物和对应的容器具有很强的相互依赖性。

原型模式

原型模式实现的功能就是对象的拷贝,只不过这种拷贝的功能是在类中定义好的,即在定义类的时候就定义好了一个clone的接口,当这个类对应的对象在某一时刻需要拷贝出另一个对象时,只需调用这个对象的clone方法即可返回一个本对象的克隆体,那么为什么不直接实例化一个新的对象而要采用这种克隆的机制呢?想象一下如果一个类的某些属性的值需要从数据库中查询,这样每实例化一个新类就需要做查询的耗时操作,这时候如果直接用一个已有的对象去clone出一个新的对象就可以避免诸如数据库查询之类的耗时操作,提高了软件的执行效率。

结构型设计模式

对象和谁有关 关注类和对象的组合,继承的概念被用来组合接口和定义组合对象获得新功能的方式。

组合模式

组合模式的要点在于组合和结构,通俗来讲就是通过不同的组合来形成一个体系结构,实现要点是list的使用,以上述demo为例,CEO的下属包含headSales和headMarketing,即CEO这个对象的下属list里面只要添加headSales和headMarketing即可,所以如果把CEO理解为一个东西的话它是由headSales和headMarketing组合而成的(如果没有这两者真不知道CEO存在的意义是什么,一自己当自己的CEO?),而headSales又有若干个salesExecutive下属,所以headSales对象的下属list里面应该添加若干个salesExecutive对象,以此类推(headMarketing由若干个clerk组成)。至此,通过不断的组合,我们就可以由salesExecutive和clerk一路不断组合直到CEO,这就是“组合”的含义,同时也体现了很强的层级关系。

装饰者模式

装饰者模式(Decorator Pattern)的目的是向一个现有的对象添加新的功能,同时又不改变其结构,这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供额外的功能。

装饰者模式的主要思路是通过一个新类(Decorator )将原来的类包装起来,在Decorator 中给原来的类添加新的功能。

装饰者模式顾名思义就是起到一个装饰的作用,即在不改变原来类结构的前提下增加一些新的功能,这种模式一般会产生一个专门的装饰类,联想结构型设计模式的定义(描述不同类之间的关系),装饰者模式实际上描述的就是一个装饰与被装饰的关系,结合上面的demo,被装饰类是实现了shape接口的Rectangle类和Circle类,而装饰类ShapeDecorator是一个抽象装饰类,在其内部定义了装饰shape的方法draw,事实上是一种方法重写(准确来说是增加方法功能),然后在ShapeDecorator的子类RedShapeDecorator中的draw调用了起装饰作用的setRedBorder方法最终达到装饰实现shape子类的目的,从最终的输出也可以看出,装饰类的作用实际上就是在原有类的基础上新增加新的东西,还有一个比较接近现实的例子是玩游戏时开局一个英雄,玩着玩着英雄的装备越来越多、英雄的技能越来越多、英雄的皮肤越来越多,这些效果实际上都是在原来开局裸体(额实在不知道用什么形容词,懂我意思就好~)英雄的基础上装饰进去的,很好地体现了装饰的精髓。

代理模式

现实生活中代理的例子其实很多,比如大家搭建服务器从而实现访问某些xx的网址的访问,其原理其实就是在云端搭建一台云主机,这台主机的地址一般是在可以访问你当前计算机不能访问的xx网址的地域(比如东亚的计算机可以访问很多nj访问不到的xx网址),所以当你想要从xx网址获取信息的时候就可以先把请求发给你搭建的云主机,让它去访问xx,然后再把信息返回给你,这样就像你直接访问了xx一样,这就是代理的意思。回到设计模式,代理模式实际上讲的就是一种“代理访问”的概念,当A类不能暴露给B类而B类又想调用A类的方法的时候必须通过一种折中的方法,即B类通过向可以调用A类的C类发送请求从而让C类调用A类干同样的事情,就是这个意思……
具先实现其实也很简单,就是一个代理类将被代理类包裹起来,只对外界暴露调用被代理类方法的方法,从而实现代理模式,需要特别注意的是代理模式和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口,和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制

享元模式

顾名思义,享元模式体现的就是一种“分享”的实质,即当很多地方都需要用到一个类的对象而实例化这个类又需要耗费很多资源的时候我们就可以把这个类的对象抽取出来,仅仅实例化一次,当以后需要实例化这个类的对象的时候直接把之前实例化的对象返回即可,比如demo中需要实例化不同颜色不同形状的shape对象,而这些对象的存在状态就那么几种,所以使用一个Factory类,当第一次接收到实例化shape类的请求时进行一次实例化并将实例化得到的结果存下来,以后再接收到实例化的请求时直接把之前实例化的同类型的对象返回即可,这样可以大大提高程序执行的效率。

桥接模式

当一个抽象类有多个实现时,通常用集成来协调他们。抽象类定义对该抽象的接口,而具体子类则用不同方式加以实现。但是此方法的缺点是将子类的抽象部分和实现部分固定在了一起,使得难以对抽象部分和实现部分进行修改、扩充和重用。
实现抽象化和实现化之间的解耦,具体到上述demo,抽象化指的是 draw redCircle和draw greenCircle,如果不使用桥接模式,一般的实现方法是根据用户指令的不同(以参数的形式体现),实现不同的draw方法,而使用桥接模式,Circle类不用关心具体如何根据用户传入参数的不同实现不同的draw方法(即实现化部分),Circle类只需要根据用户传入接口的不同调用draw方法即可,具体的实现全都交给了DrawAPI(GreenCircle、ReadCircle)来做,即将draw这个功能的抽象化放在Circle类,实现化放在DrawAPI(GreenCircle、ReadCircle),从而实现了抽象化和实例化的分离。

适配器模式

(这个模式描述的不是很好,感觉还是demo更容易理解一点)
作为两个不兼容的接口之间的桥梁,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
注意,要点是要在原来类的基础上使原本不兼容的功能变得兼容。
Adapter类一般是用来实现与原有类不兼容的功能,比如demo中的MediaAdapter实现了MediaPlayer没有的特殊功能,用户只要调用AudioPlayer中的play方法,AudioPlayer会自动根据音频的类型选择不同的play方式,当音频类型不符合传统player的能力时AudioPlayer会使用adapter去调用之前不兼容的方法(功能),这样就实现了所谓的适配。

类适配器和对象适配器的区别:
类适配器的重点在于类,是通过构造一个继承Adaptee类来实现适配器的功能;
对象适配器的重点在于对象,是通过在直接包含Adaptee类来实现的,当需要调用特殊功能的时候直接使用Adapter中包含的那个Adaptee对象来调用特殊功能的方法即可。

行为型设计模式

对象与对象在干嘛
这些设计模式特别关注对象之间的通信

模板模式

模板方法模式顾名思义就是定义了一个特殊的方法,这个方法的大体框架是写死的,比如demo中抽象类Game的play方法,它规定了所有实现类的play方法有且仅能有模板方法中定义中的行为,但是这些行为具体如何实现则不是模板方法所关心的,说白了就是模板方法规定了如果调用这个方法会干嘛,但是怎么去干就不是它所关心的重点了。

观察者模式

观察者模式用一句话描述就是当一个类的对象(被观察者)的状态发生改变时同时其他依赖于它的对象(观察者)的状态也做相应的改变(做相应的动作)。

迭代器模式

迭代器模式本质上就是一种遍历聚合对象的方式,这里的聚合对象一般具有较多的实例,比如java中的list等,也就是说对于有些对象,我们更加偏向于它的属性而不是行为,而迭代器模式提供了一种较为隐蔽的遍历这些对象属性的方法,通过经典的hasnext方法和next方法的配合使用,从而实现顺序访问聚合对象中各个元素, 而又无须暴露该对象的内部表示。

责任链模式

责任链模式的本质就是一条链,通过demo可以发现其实现方式和数据结构中的链表有很相似的地方,思想就是形成一条链,如果当前节点处理不了某些行为,则把这个行为请求转移到其下一级,以此类推,比较常见的实例就是java或者python中经常用到的try catch机制,当某个方法有可能抛出异常而当前方法无法处理的时候我们就会可能将这个异常throw到外层,即责任链中的下一级。

备忘录模式

备忘录模式的本质就是一种备份机制,其思路是将对象的状态在用户需要的时候备份下来,当需要状态回滚的时候直接将将对象的状态恢复到之前备份的状态,我们经常用的git版本控制管理系统其实就是一个特殊的备忘录模式,其在你需要的时候将你的仓库备份下来,这样你就可以在后期的开发中随时找到你之前备份的仓库状态,但是需要注意的是备忘录模式的重点是对象,其真正的目的是将单个对象的状态保存下来,至于其他的状态备份则不是它所侧重的。

命令模式

命令模式实质上就是将命令抽象到一个具体的类中,即这个类是专门去执行某个命令的,比如demo中,SellStock就是专门执行sell这个命令的,当用户需要sell的时候只要实例化SellStock然后excute就可以完成sell,还有一个比较常用的例子是GUI开发中按钮(button)的作用,每一个按钮都是一个对象,当用户点击某个按钮后就会触发一个相应的命令,用户看到的是点击按钮产生效果,而代码层面上是实例化的按钮对象执行类似于demo中的excute方法完成自己的“命令”。

状态模式

状态模式将各个状态所对应的操作分离开来,即对于不同的状态,由不同的子类实现具体操作,不同状态的切换由子类实现,比如上面的demo,同样是实现doAction根据不同的状态执行不同的逻辑,按照传统的方法需要使用if else进行判断,但是使用状态模式则可以将不同的状态实例化为不同的子类,然后在不同的子类(实际上是不同的状态)中实现不同的逻辑,客户端使用的时候只需要实例化不同的状态的子类就可以调用不同状态下的同名方法。

访问者模式

访问者模式解决的是根据访问者的不同而执行不同的行为,即同样一个方法(方法名相同),但是当A调用这个方法时执行的是逻辑A,B调用这个方法时执行逻辑B,这种情况下就需要使用访问者模式来实现。具体到demo,我们想要实现不同的ComputerPart调用accept的时候执行不同的逻辑,只需要构造一个访问者类ComputerPartDisplayVisitor,它根据accept的调用者的不用执行不同的逻辑,而调用者只需要将this传入accept方法即可,accept方法会根据传入的参数类型的不同调用不同的逻辑(visit)。

策略模式

当一个类的行为需要根据不同的状态改变时就需要使用策略模式,比如demo中Context类的executeStrategy方法执行的逻辑需要根据Context的Strategy成员的状态的变化而变化,传统地可以通过if else语句来实现对Strategy状态的判断进而实现不同的算法,但是如果采用策略模式,Context类就不必关心当前Strategy的状态,而将这种执行不同算法的控制权交给了客户端。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值