设计模式(一) | 啥是工厂模式和策略模式?

category: 大话设计模式

简单工厂模式与策略模式

前言

  • 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
  • 使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
  • 在介绍设计模式之前需要先介绍一下面向对象的特性UML类图

面向对象的特点

  • 封装、继承、多态。

UML类图

  • 在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)
  • 在UML类图中矩形框表示一个类,类分三层,第一层是;类的名称,如果是抽象类,则用斜体显示,第二层表示特性,是字段和属性,第三层表示操作,通常是方法和行为。
  • 注意前面符号,“+”表示public,“-”表示private,“#”表示protected。
  • 【泛化关系】:是一种继承关系,表示一般与特殊的关系,它指定了子类如何具体化父类的所有特征和行为。例如:老虎是动物的一种,即有老虎的特性也有动物的共性。 【箭头指向】:带三角箭头的实线,箭头指向父类
  • 【实现关系】:是一种类与接口的关系,表示类是接口所有特征和行为的实现. 【箭头指向】:带三角箭头的虚线,箭头指向接口
  • 【关联关系】:是一种拥有的关系,它使一个类知道另一个类的属性和方法;如:老师与学生,丈夫与妻子关联可以是双向的,也可以是单向的。双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头。 【代码体现】:成员变量 【箭头及指向】:带普通箭头的实心线,指向被拥有者
  • 【聚合关系】:是整体与部分的关系,且部分可以离开整体而单独存在。如车和轮胎是整体和部分的关系,轮胎离开车仍然可以存在。聚合关系是关联关系的一种,是强的关联关系;关联和聚合在语法上无法区分,必须考察具体的逻辑关系。 【代码体现】:成员变量 【箭头及指向】:带空心菱形的实心线,菱形指向整体
  • 【组合关系】:是整体与部分的关系,但部分不能离开整体而单独存在。如公司和部门是整体和部分的关系,没有公司就不存在部门。组合关系是关联关系的一种,是比聚合关系还要强的关系,它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期。

【代码体现】:成员变量

【箭头及指向】:带实心菱形的实线,菱形指向整体

  • 【依赖关系】:是一种使用的关系,即一个类的实现需要另一个类的协助,所以要尽量不使用双向的互相依赖.

【代码表现】:局部变量、方法的参数或者对静态方法的调用

【箭头及指向】:带箭头的虚线,指向被使用者

  • 各种关系的强弱顺序:
    1. 泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖
  • 下面这张UML图,比较形象地展示了各种类图关系:

简单工厂模式

  • 工厂模式介绍
  • 工厂模式专门负责将大量有共同接口的类实例化,工厂模式可以动态决定将哪一个类实例化,不必事先知道要实例化那一个类。
  • 工厂模式的几种形态:
  • 简单工厂模式:又称静态工厂方法模式。
  • 工厂方法模式:又称多态性工厂模式。
  • 抽象工厂模式:又称 工具箱模式。
  • 简单工厂模式的举例
    1. //抽象产品角色
    2. public interface Car{
    3. public void drive();
    4. }
    5. //具体产品角色
    6. public class Benz implements Car{
    7. public void drive() {
    8. System.out.println("Driving Benz ");
    9. }
    10. }
    11. public class Bmw implements Car{
    12. public void drive() {
    13. System.out.println("Driving Bmw ");
    14. }
    15. }
    16. //工厂类角色
    17. public class Driver{
    18. //工厂方法.注意 返回类型为抽象产品角色
    19. public static Car driverCar(String s)throws Exception{
    20. //判断逻辑,返回具体的产品角色给Client
    21. if(s.equalsIgnoreCase("Benz"))
    22. return new Benz();
    23. else if(s.equalsIgnoreCase("Bmw"))
    24. return new Bmw();
    25. else throw new Exception();
    26. }
    27. }

策略模式

  • 定义:它定义了算法家族,分别封装起来,让他们之间可以可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
  • Strategy类,定义了所有的支持的算法的公共接口。
    1. abstract class Strategy{
    2. //算法方法
    3. public void AlgorithmInterface();
    4. }
  • ConcreteStrategy类封装了具体的算法或行为,继承Strategy类。
    1. public class ConcreteStrategyA extend Strategy{
    2. //算法A实现方法
    3. public void AlgorithmInterface(){
    4. //算法A实现方法
    5. }
    6. }
    7. public class ConcreteStrategyB extend Strategy{
    8. //算法B实现方法
    9. public void AlgorithmInterface(){
    10. //算法B实现方法
    11. }
    12. }
  • Context类,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
    1. public class Context{
    2. Strategy strategy;
    3. public Context(Strategy strategy){ //初始化时,传入具体的策略对象
    4. this.strategy = strategy;
    5. }
    6. //上下文接口
    7. public void ContextInterface(){ //根据具体的策略对象调用其算法方法
    8. strategy.AlgorithmInterface();
    9. }
    10. }
    11. //主函数代码:
    12. public static void main(String[] args) {
    13. Context context;
    14. //由于实例化不同的策略,在调用context.AlgorithmInterface();时,所获得的结果也不同。
    15. context = new Context(new ConcreteStrategyA());
    16. context.AlgorithmInterface();
    17. context = new Context(new ConcreteStrategyB());
    18. context.AlgorithmInterface();
    19. }

策略与工厂结合

  • 修改Context类
    1. public class Context{
    2. Strategy strategy = null; //声明一个接口对象
    3. public Context(String type){ //初始化时,在Context类中实现简单工厂的应用。
    4. switch(type){
    5. case "需求一":
    6. Strategy s1 = new ConcreteStrategyA();
    7. strategy = s1;
    8. break;
    9. case "需求二":
    10. Strategy s2 = new ConcreteStrategyB();
    11. strategy = s2;
    12. break;
    13. }
    14. }
    15. public double GetResult(){
    16. return strategy..AlgorithmInterface();
    17. }
    18. }
  • 简单工厂模式与策略与工厂结合的客户端代码对比
    1. //工厂模式用法
    2. Strategy s = StrategyFactory.createStrategy(type);
    3. ... = s.GetResult();
    4. //策略与工厂结合
    5. Context c = Context(type);
    6. ... = c.GetResult();
  • 总结:简单工厂模式,客户端需要两个类,Strategy和StrategyFactory,而策略与工厂结合只需要一个类,Context类。降低了耦合性。

策略模式解析

  • 策略模式是一种定义一系列算法的方法,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
  • 优点:
  • 简化单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试,
  • 将一系列行为封装到一个个类中时,可以在这些行为的类中消除条件语句。
  • 只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑运用策略模式处理这种可能性变化。

原文发布于微信公众号 - 轮子工厂(Programmer-ing)

原文发表时间:2017-08-31

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏zaking's

js算法初窥06(算法模式03-函数式编程)

13030
来自专栏Lambda

JavaScript排序算法详解

JS家的排序算法 引子 有句话怎么说来着: 雷锋推倒雷峰塔,Java implements JavaScript. 当年,想凭借抱Java大腿火一把...

33580
来自专栏数据结构与算法

P1774 最接近神的人_NOI导刊2010提高(02)

题目描述 破解了符文之语,小FF开启了通往地下的道路。当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案。而石门上方用古代文写着“...

27660
来自专栏C语言及其他语言

[每日一题]宏定义

前面题目主要是自定义函数的题,相信经过这些题目的训练,大家对自定义函数的理解想必更近了一步。接下来呢,我们主要来练习跟自定义函数异曲同工的宏定义,先看看下面这题...

36160
来自专栏我杨某人的青春满是悔恨

Swift API 设计指南(下)

一般来说,默认参数比方法族(method families)更可取,因为它减轻了 API 使用者的认知负担。

8420
来自专栏机器之心

除了冒泡排序,你知道Python内建的排序算法吗?

Timsort 是一种对真实数据非常有效的排序算法。Tim Peters 在 2001 年为 Python 编程语言创造了 Timsort。Timsort 首先...

7920
来自专栏小詹同学

【记录帖】(No.001)从零打卡刷Leetcode

小詹一直觉得自己编程能力不强,想在网上刷题,又怕不能坚持。不知道有木有和小伙伴和小詹一样想找个人一起刷题呢?欢迎和小詹一起定期刷leetcode,每周一周五更新...

12630
来自专栏owent

不知道是哪一年的腾讯马拉松题目 照片评级 解题报告

结果就一不小心看到了这个充满回忆的ACM模式竞赛,还有咱腾讯的,就忍不住看了一下。

7110
来自专栏跟着阿笨一起玩NET

UML类图几种关系的总结

本文转载:http://blog.csdn.net/tianhai110/article/details/6339565

9110
来自专栏数据结构与算法

1269 匈牙利游戏 2012年CCC加拿大高中生信息学奥赛

1269 匈牙利游戏 2012年CCC加拿大高中生信息学奥赛 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond...

454100

扫码关注云+社区

领取腾讯云代金券