大话设计模式笔记一
类图中的关系
在正式开始学习前,需要先复习一下类图的相关知识。因为在设计模式中大量使用类图来表达一个设计模式的结构。
类图复习
首先我们看到了一个矩形框,他代表一个类。类图分为三层,第一层表示类的名称,如果是抽象类则用斜体表示。第二层是类的特性,通常包括字段和属性。第三层是类的操作,通常是方法或行为。”+“表示“public”,“-”表示“private,”#“表示”protected“。
接口
如图所示,为接口的一种表示方式,与类图的区别主要是顶部有<<interface>>
的显示。非常明显的,第一行是接口名称,第二行是接口方法。接口还可以用棒棒糖表示法来表示:
如图所示,唐老鸭类实现了“讲人话接口"。
类与类的关系——继承
首先自然是继承关系了,如图:
继承关系使用空心三角+实线来表示,其中箭头指向父类。
类与接口的关系——实现
如图所示,实现关系通过空心三角+虚线来表示,箭头指向被实现的接口。
类与类的关系——关联
关联关系,如图所示,通过实线箭头表示。关联关系表示两者之间具有使用关系,如图中的企鹅需要知道(引用)了这个类。
类与类的关系——聚合
聚合关系代表一种弱的“拥有关系“,即A对象可以包含B对象,但B对象不是A的一部分。图中的例子举的不太好,但用面向对象的方式理解的话是没有问题的,即雁群类中包含一个大雁List,但大雁类中并不包含雁群类。
类与类的关系——组合(合成)
组合关系代表一种强的“拥有关系”,体现了严格的部分和整体的关系,部分和整体的生命周期一致。组合关系用实心的菱形 + 实线箭头来表示。另外,我们在连线上标了两个数字,这被称为基数。表示这一端的类可以有几个实例。一只鸟有两只翅膀,所以这里就标着1和2了。另外,关联关系和聚合关系都可以标注基数。
类与类的关系——依赖
依赖关系,表示该类在另一个类的方法参数上,表明该类的运行需要此类,如动物的新陈代谢需要氧气和水,则动物依赖氧气和水。依赖关系用虚线箭头来表示。
0.简单工厂模式(Simple Factory Pattern)
解决的问题
在开发时,很多时候都会遇到多个类有共同父类的情况。一旦类多起来就记不住名称了。如果我们希望在使用这些子类时不需要知道具体的类名,只要知道一个参数就可以给我们返回一个需要的对象,那么就用得到简单工厂模式了。
类图结构
简单工厂模式如图所示结构,这个类图中包含三类角色:
-
Factory(工厂角色)
工厂角色即工厂类,它是该模式的核心角色。工厂类中提供了核心方法factoryMethod(),返回一个抽象产品类,即所有的具体产品类的父类。
-
Prodcut(抽象产品角色)
抽象产品角色是简单工厂模式中所有对象的父类,负责描述所有实例共有的公共接口。
-
ConcreteProduct(具体产品角色)
具体产品角色是简单工厂模式的创建目标。
其中,核心类Factory大概长这样:
public class Factory{
public static Product factoryMethod(String arg){
if(arg.equals("A")){
return new ConcreteProductA();
}
if(arg.equals("B")){
return new ConcreteProductB();
}
}
}
好处与坏处
大致来讲,简单工厂模式通过一个工厂类封装了具体的获得实现类的逻辑,使得使用者不需要知道具体的实现类即可很快的获得一个需要的实体类。
但由于工厂类包含了所有的逻辑,一旦其崩溃,则整个系统都会崩溃。同时随着类的增多需要不断修改工厂类,工厂类的业务逻辑会十分复杂,违背了开闭原则。
Tips
可以看到,这里对简单工厂模式标注的是0,代表他并不属于23种设计模式。但为什么还需要了解他呢,因为他使用的实在是太频繁了,而且了解简单工厂模式可以更好的理解23种设计模式中的工厂方法模式。
1.策略模式(Strategy Pattern)
解决的问题
策略模式是一种定义一系列算法的方法,从概念上看,所有这些算法完成的都是相同的工作,只是实现不同。因此,我们可以使用策略模式解决相同概念但不同实现的工作,如商场打折。
类图结构
假设我们现在有一个超市正在举行打折活动,打折活动分为两种——1.打折收费 2.返利收费。我们通过策略模式实现这个需求。
类图如下:
在这个类图中,CashContext类通过构造方法传入具体的收费策略,然后根据不同的收费策略来获得计算结果:
public class CashContext{
private CashSuper cs;
public CashContext(CashSuper cs){
this.cs = cs;
}
public double getResult(double money){
return cs.acceptCash(money);
}
}
而CashNormal、CashRebate、CashReturn这三个类都继承自CashSuper类,实现了acceptCash()方法:
public class CashNormal extends CashSuper{
@override
public double acceptCash(double money){
return money;
}
}
这样,我们在使用的时候只需要new一个CashContext对象,然后传入对应的子类即可。
好处与坏处
策略模式的好处十分显而易见,外部不需要知道内部的具体实现,只需要调用同样的方法就可以做出不同的实现。可以很好地提取出公共功能。
坏处也很明显,策略模式并没有减轻客户端需要判断的压力。我们可以使用策略模式+简单工厂模式的方式来减轻客户端的职责。