设计模式

设计模式


创建型模式

​ 创建型模式关注点是如何创建对象,其核心思想是要把对象的创建和使用相分离,这样使得两者能相对独立地变换

工厂模式

大体描述: 工厂方法的目的是使得创建对象和使用对象是分离的,并且客户端总是引用抽象工厂和抽象产品
​ 工程模式(Factory Pattern)为,定义一个创建对象的接口,该使用该接口的方法可以获取想要的对象,获取的对象一般为抽象类,其本身为一些实现类
​ 在定义一个实现该工厂接口的实现类工厂对象,该工厂实现了对应创建方法的具体逻辑。可获取该工厂来得到所需要的产品(也就是获取的对象)
例:

interface NumberFactory { //工厂接口
    Number parse(String s); //获取对象
}
class NumberFactoryImle{ //工厂实现对象
    override Number parse(String s){  //具体实现
        return new BigDecimal(s);
    }
}
fun main(){
    val factory: NumberFactory =  NumberFactoryImle() //获取工厂
    val product = factory.parse("1234") //使用工厂获取产品
}

抽象工厂

​ 抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂

interface Factory { //抽象工厂
    //获取产品
    fun getProduct():Product
    //获取实际工厂
    fun getFactory(s:String){
        return when(s){
            1 -> oneFactory()
            2 -> TwoFactory()
        }
    }
}

fun main(){
    val product: Product = Factory.getFactory(1).getProduct() //通过抽象工厂获取实际工厂,再获取产品
}



class oneFactory{ //实际工厂1
    override fun getProduct(){
        return SolidProduct()
    }
}

class TwoFactory{ //实际工厂2
    override fun getProduct(){
        return SolidProduct()
    }
}

abstract class Product{ //抽象产品
    abstract fun method(); 
}
class SolidPRoduct{ //实际产品
    override fun method(){
        print("产品")
    }
}

生成器

​ 也叫做建造者模式
​ 生成器模式(Builder)是使用多个“小型”工厂来最终创建出一个完整对象
​ 当我们使用Builder的时候,一般来说,是因为创建这个对象的步骤比较多,每个步骤都需要一个零部件,最终组合成一个完整的对象。

class AimBuilder{ //生成器对象
    val result = Aim() 
    fun setT1(a:Int){ //零件方法
        result.t1 =  a
    }
    fun setT2(a:String){ //零件方法
        result.t1 =  a
    } 
    fun getRusult() = return result
}

fun main(){
    Aim a = AimBuilder().setT1(1).setT2("qwq").getRuslt() //创建生成器并调用各个零件方法构建目的对象
}


class Aim(val t1:Int,var t2:String) //生成对象

原型模式

​ 原型模式,即Prototype,是指创建新对象的时候,根据现有的一个原型来创建。

class Proto(val name:String,val age:Int){ //原型类
    fun copy(){ //根据原型类创建新对象
        return Proto(this.name,this.age)
    }
}

单例

单例模式(Singleton)的目的是为了保证在一个进程中,某个类有且仅有一个实例。

结构型模式

​ 结构型模式主要涉及如何组合各种对象以便获得更好、更灵活的结构。
​ 虽然面向对象的继承机制提供了最基本的子类扩展父类的功能,但结构型模式不仅仅简单地使用继承,
​ 而更多地通过组合与运行期的动态组合来实现更灵活的功能。

适配器

​ 将一个类的接口转换成我们希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

桥接模式

​ 将抽象部分与它的实现部分分离,使它们都可以独立地变化。
例: 有3种水果,他们有3中腐烂程度,若以每个都实现来看,实现类会很多,但将实现分离,提供一个腐烂程度的接口,以此来避免实现类

abstract class Fruit(val rot:Rot){
    
}

fun main(){
    Apple(TopRot()) //定义腐烂程度
}

//腐烂接口
interface Rot()
class TopRot()

//实现类
class Apple:Fruit

组合模式

​ 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。
​ 组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
例:
​ html标签的树形节点

装饰器

动态地给一个对象添加一些额外的职责。就增加功能来说,相比生成子类更为灵活。

​ 装饰器(Decorator)模式,是一种在运行期动态给某个对象的实例增加功能的方法。
例: java 中io流, 普通IO流可new BufferedInputStream(IO流); 放入这个构造参数中 被包装,附加新的功能

外观模式

​ 为子系统中的一组接口提供一个一致的界面。Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

class FunctionWrapper{ //高层接口
    //提供的接口
    val say = Say()
    val use = Use() 
    //使用接口
    fun say(){
        this.say
    }
    fun use(){
        this.use
    }
}

享元模式

​ 运用共享技术有效地支持大量细粒度的对象。
​ 享元(Flyweight)的核心思想很简单:如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行

public class Student {
    // 持有缓存:
    private static final Map<String, Student> cache = new HashMap<>();

    // 静态工厂方法:
    public static Student create(int id, String name) {
        String key = id + "\n" + name;
        // 先查找缓存:
        Student std = cache.get(key);
        if (std == null) {
            // 未找到,创建新对象:
            System.out.println(String.format("create new Student(%s, %s)", id, name));
            std = new Student(id, name);
            // 放入缓存:
            cache.put(key, std);
        } else {
            // 缓存中存在:
            System.out.println(String.format("return cached Student(%s, %s)", std.id, std.name));
        }
        return std;
    }

    private final int id;
    private final String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }
}

代理模式

​ 为其他对象提供一种代理以控制对这个对象的访问。

class AProxy(private val a:A): A{
    fun do(){
        ~~~方法前
        this.a.do()
        ~~~方法后
    }
    
}

行为型模式

​ 行为型模式主要涉及算法和对象间的职责分配。通过使用对象组合,行为型模式可以描述一组对象应该如何协作来完成一个整体任务。

责任链

​ 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
​ 将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

class Handler{
    fun process(r:Request){}
}

class HandlerChain{
    val list = ArrayList<Handler>()
    fun addHandler(h: Handler){ list.add(h)}
    fun process(r:Request){
        list.foreach{it.process(r)}
    }
}

命令模式

​ 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。

class Editor{  
}
fun main(){
    val e = Editor()
    CopyCommand(e).execute
}


interface Command

class CopyCommand:Command{
    fun execute()
}

解释器

​ 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
例:
​ 当我们使用JDBC时,执行的SQL语句虽然是字符串,但最终需要数据库服务器的SQL解释器来把SQL“翻译”成数据库服务器能执行的代码,
​ 这个执行引擎也非常复杂,但对于使用者来说,仅仅需要写出SQL字符串即可。

迭代器

​ 提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

中介模式

​ 用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互
例:
​ 在一个UI界面中,使用一个中介类来管理各个UI中模块,并且管理他们之间的交互

备忘录

​ 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
例:
​ 一个UI中的操作状态,序列化到本地,在需要时,读取本地,反序列化回来

观察者

​ 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

public class Store {
    private List<ProductObserver> observers = new ArrayList<>();
    private Map<String, Product> products = new HashMap<>();

    // 注册观察者:
    public void addObserver(ProductObserver observer) {
        this.observers.add(observer);
    }

    // 取消注册:
    public void removeObserver(ProductObserver observer) {
        this.observers.remove(observer);
    }

    public void addNewProduct(String name, double price) {
        Product p = new Product(name, price);
        products.put(p.getName(), p);
        // 通知观察者:
        observers.forEach(o -> o.onPublished(p));
    }

    public void setProductPrice(String name, double price) {
        Product p = products.get(name);
        p.setPrice(price);
        // 通知观察者:
        observers.forEach(o -> o.onPriceChanged(p));
    }
}

状态模式

​ 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
例:
​ QQ的离线状态不会受到消息提示

策略模式

​ 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化
​ 策略模式:Strategy,是指,定义一组算法,并把其封装到一个对象中。然后在运行时,可以灵活的使用其中的一个算法
例:
​ java中list的sort排序方法,可以传入排序逻辑

模版方法

​ 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
​ 模板方法(Template Method)是一个比较简单的模式。它的主要思想是,定义一个操作的一系列步骤,对于某些暂时确定不下来的步骤,
​ 就留给子类去实现好了,这样不同的子类就可以定义出不同的步骤。

abstract class Draw{
    fun draw(){
        cloor()
        
    }
    abstract cloor()
}
//定义了抽象方法cloor,具体的操作由其派生类实现,并且 draw方法提供了具体的算法

访问者

​ 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
例:
​ 我们要处理一个图片,在获取到这个图片后,需要根据图片的类型来匹配对应的处理逻辑
​ 此时,若要添加一个新的图片类型处理,会修改原有代码
​ 可以使用访问者模式,将处理图片的方法与获取图片的方法分离开

//访问者接口
interface Vistor{
    //处理图片
    fun handlerImage()
}
//图片
class Image{
    fun handler(v:Vistor){
        v.handlerImage()
    }
    //获取图片
    fun scan(f:File,v:Vistor){
        if (file.isDirectory()) {
            // 让访问者处理文件夹:
			visitor.visitDir(file);
			for (File sub in file.listFiles()) {
                // 递归处理子文件夹:
				scan(sub, visitor);
			}
		} else if (file.isFile()) {
            // 让访问者处理文件:
			visitor.visitFile(file);
		}
    }
}
posted @ 2025-08-12 22:20  LittleD-  阅读(3)  评论(0)    收藏  举报