设计模式(一) | 啥是工厂模式和策略模式?
时间:2022-06-06
本文章向大家介绍设计模式(一) | 啥是工厂模式和策略模式?,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
category: 大话设计模式
简单工厂模式与策略模式
前言
- 设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
- 使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
- 在介绍设计模式之前需要先介绍一下面向对象的特性和UML类图。
面向对象的特点
- 封装、继承、多态。
UML类图
- 在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)
- 在UML类图中矩形框表示一个类,类分三层,第一层是;类的名称,如果是抽象类,则用斜体显示,第二层表示特性,是字段和属性,第三层表示操作,通常是方法和行为。
- 注意前面符号,“+”表示public,“-”表示private,“#”表示protected。
- 【泛化关系】:是一种继承关系,表示一般与特殊的关系,它指定了子类如何具体化父类的所有特征和行为。例如:老虎是动物的一种,即有老虎的特性也有动物的共性。 【箭头指向】:带三角箭头的实线,箭头指向父类
- 【实现关系】:是一种类与接口的关系,表示类是接口所有特征和行为的实现. 【箭头指向】:带三角箭头的虚线,箭头指向接口
- 【关联关系】:是一种拥有的关系,它使一个类知道另一个类的属性和方法;如:老师与学生,丈夫与妻子关联可以是双向的,也可以是单向的。双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头。 【代码体现】:成员变量 【箭头及指向】:带普通箭头的实心线,指向被拥有者
- 【聚合关系】:是整体与部分的关系,且部分可以离开整体而单独存在。如车和轮胎是整体和部分的关系,轮胎离开车仍然可以存在。聚合关系是关联关系的一种,是强的关联关系;关联和聚合在语法上无法区分,必须考察具体的逻辑关系。 【代码体现】:成员变量 【箭头及指向】:带空心菱形的实心线,菱形指向整体
- 【组合关系】:是整体与部分的关系,但部分不能离开整体而单独存在。如公司和部门是整体和部分的关系,没有公司就不存在部门。组合关系是关联关系的一种,是比聚合关系还要强的关系,它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期。
【代码体现】:成员变量
【箭头及指向】:带实心菱形的实线,菱形指向整体
- 【依赖关系】:是一种使用的关系,即一个类的实现需要另一个类的协助,所以要尽量不使用双向的互相依赖.
【代码表现】:局部变量、方法的参数或者对静态方法的调用
【箭头及指向】:带箭头的虚线,指向被使用者
- 各种关系的强弱顺序:
-
泛化
=
实现
>
组合
>
聚合
>
关联
>
依赖
-
- 下面这张UML图,比较形象地展示了各种类图关系:
简单工厂模式
- 工厂模式介绍
- 工厂模式专门负责将大量有共同接口的类实例化,工厂模式可以动态决定将哪一个类实例化,不必事先知道要实例化那一个类。
- 工厂模式的几种形态:
- 简单工厂模式:又称静态工厂方法模式。
- 工厂方法模式:又称多态性工厂模式。
- 抽象工厂模式:又称 工具箱模式。
- 简单工厂模式的举例
-
//抽象产品角色
-
public
interface
Car{
-
public
void drive();
-
}
-
//具体产品角色
-
public
class
Benz
implements
Car{
-
public
void drive()
{
-
System.out.println("Driving Benz ");
-
}
-
}
-
public
class
Bmw
implements
Car{
-
public
void drive()
{
-
System.out.println("Driving Bmw ");
-
}
-
}
-
//工厂类角色
-
public
class
Driver{
-
//工厂方法.注意 返回类型为抽象产品角色
-
public
static
Car driverCar(String s)throws
Exception{
-
//判断逻辑,返回具体的产品角色给Client
-
if(s.equalsIgnoreCase("Benz"))
-
return
new
Benz();
-
else
if(s.equalsIgnoreCase("Bmw"))
-
return
new
Bmw();
-
else
throw
new
Exception();
-
}
-
}
-
策略模式
- 定义:它定义了算法家族,分别封装起来,让他们之间可以可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
- Strategy类,定义了所有的支持的算法的公共接口。
-
abstract
class
Strategy{
-
//算法方法
-
public
void
AlgorithmInterface();
-
}
-
- ConcreteStrategy类封装了具体的算法或行为,继承Strategy类。
-
public
class
ConcreteStrategyA extend Strategy{
-
//算法A实现方法
-
public
void
AlgorithmInterface(){
-
//算法A实现方法
-
}
-
}
-
public
class
ConcreteStrategyB extend Strategy{
-
//算法B实现方法
-
public
void
AlgorithmInterface(){
-
//算法B实现方法
-
}
-
}
-
- Context类,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。
-
public
class
Context{
-
Strategy strategy;
-
public
Context(Strategy strategy){
//初始化时,传入具体的策略对象
-
this.strategy = strategy;
-
}
-
//上下文接口
-
public
void
ContextInterface(){
//根据具体的策略对象调用其算法方法
strategy.AlgorithmInterface();
-
}
-
}
-
//主函数代码:
-
public
static
void main(String[] args)
{
-
Context context;
-
//由于实例化不同的策略,在调用context.AlgorithmInterface();时,所获得的结果也不同。
-
context =
new
Context(new
ConcreteStrategyA());
context.AlgorithmInterface();
-
context =
new
Context(new
ConcreteStrategyB());
context.AlgorithmInterface();
-
}
-
策略与工厂结合
- 修改Context类
-
public
class
Context{
-
Strategy strategy =
null;
//声明一个接口对象
-
public
Context(String type){
//初始化时,在Context类中实现简单工厂的应用。
-
switch(type){
-
case
"需求一":
-
Strategy s1 =
new
ConcreteStrategyA();
strategy = s1;
-
break;
-
case
"需求二":
-
Strategy s2 =
new
ConcreteStrategyB();
strategy = s2;
-
break;
-
}
-
}
-
public
double
GetResult(){
-
return strategy..AlgorithmInterface();
-
}
-
}
-
- 简单工厂模式与策略与工厂结合的客户端代码对比
-
//工厂模式用法
-
Strategy s =
StrategyFactory.createStrategy(type);
-
...
= s.GetResult();
-
//策略与工厂结合
-
Context c =
Context(type);
-
...
= c.GetResult();
-
- 总结:简单工厂模式,客户端需要两个类,Strategy和StrategyFactory,而策略与工厂结合只需要一个类,Context类。降低了耦合性。
策略模式解析
- 策略模式是一种定义一系列算法的方法,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
- 优点:
- 简化单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试,
- 将一系列行为封装到一个个类中时,可以在这些行为的类中消除条件语句。
- 只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑运用策略模式处理这种可能性变化。
- HTTP请求详解
- 漫谈Java IO之 NIO那些事儿
- 1593: [Usaco2008 Feb]Hotel 旅馆
- BZOJ 1823: [JSOI2010]满汉全席(2-SAT)
- 3360: [Usaco2004 Jan]算二十四
- JavaScript 数据类型
- 3361: [Usaco2004 Jan]培根距离
- Java NIO
- 1342: [Baltic2007]Sound静音问题
- 加深理解HTTP请求---网络基础TCP/IP
- BZOJ2199: [Usaco2011 Jan]奶牛议会(2-SAT)
- 数据结构之链表、栈和队列 java代码实现
- 洛谷P3209 [HNOI2010]PLANAR(2-SAT)
- javascript 面向对象(多种创建对象的方式)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- kubernetes之StatefulSet控制器
- 如何使用 S3CMD 访问 COS 服务
- 利用STS临时密钥服务快速搭建直传页面的实践
- codeforces 1436C(二分+数学)
- WAF案例:为什么curl可以wget不行?
- React进阶(4)-拆分Redux-将store,Reducer,action,actionTypes独立管理
- React进阶(5)-分离容器组件,UI组件(无状态组件)
- React进阶(6)-react-redux的使用
- Kubernetes 1.19.0——服务svc(2)
- Android菜单的定义及ActionBar的实现
- 3分钟短文:Laravel表单验证的“指挥中心”:FormRequest
- 10 种跨域解决方案(附终极方案)
- 架构师教你kill祖传石山代码重复/大量ifelse
- TKE集群,一次磁盘挂载问题处理
- Linux Load Average详解