设计模式
面向对象
工厂方法
Factory method Pattern 实现了“工厂”概念的面向对象设计模式。定义一个创建对象的接口,但让实现这个接口的类决定实例化哪个类。
通俗的说法:女朋友想要可乐,你需要体贴的问她要百事还是可口可乐吗?不需要把,你只需要和服务员说来瓶可乐即可。服务员会自动拿百事可乐或者可口可乐
classDiagram
Cola <|-- CocoCola: 实现可乐接口
Cola <|-- PeisiCola: 实现可乐接口
Cola: object cola
Cola: getCola()
GirlFriend --> Cola: 女主子要可乐
package com.tyrantqiao.algorithms.pattern;
import com.tyrantqiao.algorithms.pattern.shape.Circle;
import com.tyrantqiao.algorithms.pattern.shape.IShape;
import com.tyrantqiao.algorithms.pattern.shape.Triangle;
import java.lang.reflect.InvocationTargetException;
/**
* date: 2018/4/30
* Description: 工厂模式
* blog https://tyrantqiao.github.io/Blog
* <p>
* 解决的什么问题:
* 比如说现在要cricle.paint()
* 在God类中{@code Shape circle=new Circle();}
* {@code circle.paint();}
* 假如说要加多个triangle.paint();
* 就要多定义一个 {@code Shape triangle=new Triangle();
* triangle.paint();}
* 导致God类依赖严重,臃肿
* <p>
* 解决方法就是通过工厂方式,God Class不关心具体实现Shape的细节,只管把自己想要的东西告诉{@link FactoryPattern}的getShape()方法
*
* @author tyrantqiao
* @version 0.0.1
* @see <a href="https://github.com/tyrantqiao">qiao's github</a>
*/
public class FactoryPattern {
enum ShapeEnum {
/**
* 圆形
*/
CIRCLE("circle"), Triangle("triangle");
private final String shapes;
ShapeEnum(String shapes) {
this.shapes = shapes;
}
public String getShape() {
return shapes;
}
}
/**
* @param shapeType 形状类型
* @return 获取类型
* @apiNote 存在问题,每次加类型都要修改这个方法,后期容易臃肿,改进为反射进行获取类
*/
public IShape getShape(String shapeType) {
if (ShapeEnum.CIRCLE.getShape().equals(shapeType)) {
return new Circle();
} else if (ShapeEnum.Triangle.getShape().equals(shapeType)) {
return new Triangle();
}
return null;
}
/**
* 进化版,根据类去实例化
*
* @param clazz 类
* @return 实例化后的类
*/
public IShape getShapeVersionTwo(Class<? extends IShape> clazz) {
try {
if (null != clazz) {
// 假如是内部类的话,此段代码无法运行,请注意
return clazz.getDeclaredConstructor().newInstance();
}
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
抽象工厂
抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来
俗话: 还是女票主子,出去玩总得化个美美的妆把,化妆就又需要口红,眉笔,腮红,粉底,眼线·····除了这些化妆品外,还讲究化妆的风格流派,是哥特萝莉派,还是生人勿近的女神派,这些需要的色号以及化妆品牌子型号又不同。
那怎么快速管理这些风格呢?土豪流派(抽象工厂):把每一个流派所需的化妆品放到一个化妆盒子里,这样子只要打开对应盒子,即可以拿到对应流派的化妆品
classDiagram
class GirlFriend {
factory: AbstractCosmeticFactory
}
GirlFriend: GirlFirend(AbstractCosmeticFactory)
GirlFriend: makeUp()
class AbstractCosmeticFactory{
<<interface>>
getLipstick() Lipstick
getEyebrowPencil() EyebrowPencil
}
class GothicCosmeticFactory{
<<哥特风>>
getLipstick() return new GothicLipstick()
getEyebrowPencil() return new GothicEyebrowPencil()
}
class PureCosmeticFactory{
<<清纯风>>
getLipstick() return new PureLipstick()
getEyebrowPencil() return new EyebrowPencil()
}
class Lipstick{
<<口红接口基类>>
}
class GothicLipstick{
<<哥特风口红>>
}
class PureLipstick{
<<清纯口红>>
}
Lipstick <|.. GothicLipstick: 继承
Lipstick <|.. PureLipstick: 继承
GirlFriend --* AbstractCosmeticFactory: 通过抽象工厂类获取化妆品
AbstractCosmeticFactory <|.. GothicCosmeticFactory : 实现接口
AbstractCosmeticFactory <|.. PureCosmeticFactory : 实现接口
GothicCosmeticFactory --> GothicLipstick: return new GothicLipstick()
PureCosmeticFactory --> PureLipstick: return new PureLipstick()
建造者模式
对象构建模式。将复杂对象的构建过程抽象出来,使抽象过程的不同实现方法可以构建出不同的对象。
俗话:都知道女朋友是一种神奇的主子生物,心情和天气一样阴晴不定,那么我们如何抉择怎么讲话呢?比如说我们有一个骚话模板计算器,有讲笑话,讲故事,出去吃饭等功能,不同的组合形式,不同的执行顺序都会影响到女朋友的心情。
重点来了:把这些骚话抽象成一个个按钮,按 1 是讲笑话,按 2 是讲故事,按 3 是出去吃饭,有了这些按钮,我们可以随意排列这些顺序 123、312,或者选择性挑选 31、23,都能生成一个很好和女朋友玩耍的操作模板。
Department department=new Department.Builder("数据库部门","3306")
.setMembers(···)
.setInstruments(···)
.build();
public class Department{
private String[] members;
private String[] instruments;
/**
* name 和 id必输
*/
private String name;
private String id;
private Department(Builder builder){
this.name=builder.name;
this.id=builder.id;
}
public static class Builder{
private String[] members;
private String[] instruments;
/**
* name 和 id必输
*/
private String name;
private String id;
private Builder(String name,String id){
this.name=builder.name;
this.id=builder.id;
}
public Builder setMembers(String[] members){
this.members=members;
return this;
}
public Builder setInstruments(String[] instruments){
this.instruments=instruments;
return this;
}
public Department build(){
return new Department(this);
}
}
}
原型模式
创建型模式的一种,通过复制一個已經存在的實例來返回新的實例, 而不是新建實例。被复制的实力成为原型
俗话怎么说呢,把对象引用当作一个自动回复消息模板,比如说你想自动回复“我在忙,别打扰我”,但是你不想每次都手打,那你可以选择《忙碌模板》进行快速回复,原型模型的目的就是为了快速的复制,毕竟不涉及内容的真正变更,只是浅复制 shallow copy 关于浅复制和深复制的请参考这篇文章
classDiagram
class Client{
<<God class>>
}
Client: operation() ==> prototype.clone()
class Prototype{
<<interface>>
}
class ConcretePrototype1{
<<实现类1>>
}
class ConcretePrototype2{
<<实现类2>>
}
Prototype *-- Client: import class
Prototype <|-- ConcretePrototype1: 继承
Prototype <|-- ConcretePrototype2: 继承
单例模式
在應用這個模式時,單例對象的類必須保證只有一個實例存在。許多時候整個系統只需要擁有一個的全局對象,這樣有利於我們協調系統整體的行為—wiki
俗话:只有一个你
classDiagram
class Client{
<<客户类>>
}
class Singleton{
<<单例模式>>
instance: Singleton
}
Singleton: -Singleton()
Singleton: +getInstance() Singleton
Client --* Singleton: import
Singleton --> Singleton: 返回单一实例
适配器模式(变压器模式)
(Adapter)配接器模式有時候也稱包裝樣式或者包裝。將一個類別的介面轉接成用戶所期待的.
俗话: 你在和外国友人吹水,但是语言不通(相当于接口不通),这时来了个自动翻译软件(适配器),大家就能交谈了。
对象适配器
适配器实现了其中一个对象的接口,并将另一个对象进行封装
classDiagram
class Client{
<<God class>>
}
class ClientInterface{
<<interface>>
+method(data)
}
class Service{
<<Service 不适配的服务>>
+serviceMethod(specialData)
}
class Adapter{
<<适配器模型>>
adaptee: Service
+method(data)
}
Client --> ClientInterface: 原本引入的接口
Adapter --|> ClientInterface: 继承原有接口,便于后面无缝切换
Adapter --* Service: 组合封装服务类
Client ..> Adapter: 等Adapter开发完后,迁移到这
类适配器
通过继承机制,同时继承两个对象的接口。但只能支持多重继承,比如 C++
classDiagram
class Client{
<<上帝类>>
}
class ExistingClass{
<<原有服务>>
+method(data)
}
class Service{
<<不适配的服务>>
+serviceMethod(specialData)
}
class Adapter{
+method(data)
}
Client --* ExistingClass: import
Adapter --|> ExistingClass: 继承
Adapter --|> Service: 继承
Client ..> Adapter: 等改造完后进行迁移
桥梁模式
它把事物對象和其具體行爲、具體特徵分離開來,使它們可以各自獨立的變化。事物對象僅是一個抽象的概念–wiki
俗话:比如说化妆,你需要打理头发,同时也需要整理妆容,这两个都要根据不同的场景进行适配,通过桥梁模式,把抽象和实现分离,这样子就可以让打理头发,整理妆容适配场景
classDiagram
class Pen{
<<abstract>>
color: 颜色
+setColor(Color) abstract
+paint() abstract
}
class PurePen{
<<纯粹笔>>
+paint() implements
}
class Color{
<<abstract>>
+color() abstract
}
class RedColor{
<<红色>>
+color() implements
}
Pen <|-- PurePen: 继承实现笔型号变换
Pen --* Color: 组合color的抽象类
Color <|-- RedColor: 继承实现具体颜色
合成模式
合成模式(Composite Pattern),又叫部分整體模式,是用於把一組相似的對象當作一個單一的對象
俗话:
“请我吃一道麦当劳把”
“可以啊,只能一道”
“哎哎哎,怎么还点汉堡鸡块可乐薯条了,这都四样了”
“四个刚好组一起作为套餐啊”
graph TD;
root -->|tmp文件夹| tmp
root -->|log文件夹| log
log --> |按年份查询| 2021
log --> |按年份查询| 2020
title[文件系统,每一个文件和目录都是视为文件,即root目录和2021等效]
代理模式
通过代理人 proxy 为其他对象提供代理,以控制对对象的访问。起到保护目标对象+增强目标对象的作用。
classDiagram
class Subject{
+request() void
}
class Proxy{
Proxy(Subject)
+request() void
+before() void
+after() void
}
class RealSubject{
+request() void
}
class Client{
+main(String[] args) void
}
RealSubject<..Client: create
Proxy<..Client: create
Subject<|--|>Proxy: 1-1
Subject<|..RealSubject
参考资料
- 设计模式通俗
- <<设计模式之禅>>