Java23种设计模式/GOF设计模式--创建型模式

目录

设计模式

面向对象

设计模式的六大原则

创建型模式

1、工厂模式

工厂方法(Factory method pattern)

 简单工厂

2、抽象工厂(Abstract factory pattern)

3、单例模式(Singleton pattern)

4、建造者模式(Builder Pattern)

5、原型模式(Prototype pattern)


设计模式


维基百科把设计模式分为了设计模式和软件设计模式两个WIKI,其中前者指的是GOF的设计模式,GOF设计模式针对的是C++和smalltalk等面向对象的高级语言,而软件设计模式是更大的概念,包含了更多模式,实际上后者中很多模式在Java也有广泛的应用,这里只谈GOF的23种设计模式。

面向对象


面向对象是对世界的抽象,一切皆对象,这种高级语言本身就是一种最顶层的设计。理论上讲,基于这种语言开发系统时搞清需求、设计业务流程图、设计业务实体,然后把这些实体转化成类,一个个用代码实现系统就做完了,不需要什么设计模式,早期一些小系统也就是这么做的。

然后事实却不尽如人意,原因是系统越来越复杂,需要支撑的功能越来越多,对易维护、易拓展的要求越来越高。应用不再单单跟自己打交道,应用之间往往需要相互打交道,构成庞大的系统,外部的不确定性对应用构成挑战。系统的硬件资源要求软件与之配合。

越来越多的因素要求软件要有一定的设计,最好能应付所有的问题。在越来越多的实践上,人们总结出些经验,这些经验有很多是用失败换来的。

可以说六大设计原则是设计最浓缩的精华,也是对设计模式的要求。在遵循设计原则的基础上,会不自知的使用设计模式,哪怕你还不了解设计模式。

设计模式的六大原则


1、开闭原则(Open Close Principle)

开闭原则就是说对扩展开放,对修改关闭

在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。

2、里氏代换原则(Liskov Substitution Principle)

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。

LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科

3、依赖倒转原则(Dependence Inversion Principle)

这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。

4、接口隔离原则(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。

5、迪米特法则(最少知道原则)(Demeter Principle)

为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

6、合成复用原则(Composite Reuse Principle)

原则是尽量使用合成/聚合的方式,而不是使用继承。


创建型模式

结构型模式

行为型模式


创建型模式


1、工厂模式


  • 工厂方法(Factory method pattern

工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”

在面向对象程序设计中,工厂通常是一个用来创建其他对象的对象。工厂是构造方法的抽象,用来实现不同的分配方案。工厂对象通常包含一个或多个方法,用来创建这个工厂所能创建的各种类型的对象。这些方法可能接收参数,用来指定对象创建的方式,最后返回创建的对象。

有时,特定类型对象的控制过程比简单地创建一个对象更复杂。在这种情况下,工厂对象就派上用场了。工厂对象可能会动态地创建产品对象的类,或者从对象池中返回一个对象,或者对所创建的对象进行复杂的配置,或者应用其他的操作。

UML用例图

           代码举例

例如,有一个Button类表示按钮,另有它的两个子类WinButtonMacButton分别代表Windows和Mac风格的按钮,那么这几个类和用于创建它们的工厂类在Java中可以如下实现(在此省略所有类和方法的可见性设置):

//幾個Button類
class Button{/* ...*/}
class WinButton extends Button{/* ...*/}
class MacButton extends Button{/* ...*/}

//他們的工廠類
interface ButtonFactory{
    abstract Button createButton();
}
class WinButtonFactory implements ButtonFactory{
    Button createButton(){
        return new WinButton();
    }
}
class MacButtonFactory implements ButtonFactory{
    Button createButton(){
        return new MacButton();
    }
}
  •  简单工厂

普通的工厂方法模式通常伴随着对象的具体类型与工厂具体类型的一一对应,客户端代码根据需要选择合适的具体类型工厂使用。

然而,这种选择可能包含复杂的逻辑。这时,可以创建一个单一的工厂类,用以包含这种选择逻辑,根据参数的不同选择实现不同的具体对象。这个工厂类不需要由每个具体产品实现一个自己的具体的工厂类,所以可以将工厂方法设置为静态方法。 而且,工厂方法封装了对象的创建过程。

如果创建过程非常复杂(比如依赖于配置文件或用户输入),工厂方法就非常有用了。 比如,一个程序要读取图像文件。程序支持多种图像格式,每种格式都有一个对应的ImageReader类用来读取图像。程序每次读取图像时,需要基于文件信息创建合适类型的ImageReader。这个选择逻辑可以包装在一个简单工厂中:

           代码举例

public class ImageReaderFactory {
    public static ImageReader imageReaderFactoryMethod(InputStream is) {
        ImageReader product = null;

        int imageType = determineImageType(is);
        switch (imageType) {
            case ImageReaderFactory.GIF:
                product = new GifReader(is);
            case ImageReaderFactory.JPEG:
                product = new JpegReader(is);
            //...
        }
        return product;
    }
}

2、抽象工厂Abstract factory pattern

抽象工厂是“工厂方法”的进一步升级,每个工厂生产一组产品,或者说一个产品的一组组件。

形式上工厂方法是抽象工厂的只有单一产品的特例,但概念上抽象工厂与工厂方法不同,抽象解决的是“同一种产品”的各个组件的变化性,这种变化往往是业务的需求,进而演化出不同的系列产品。参考thinkpad的T系列,E系列,他们拥有相同的键盘(thinkpad的键盘真的太好使了),但是屏幕、A面材质可能不同。

UML用例图

代码举例

//产品接口
public interface Button {}
public interface Border {}

// 实现抽象类
public class MacButton implements Button {}
public class MacBorder implements Border {}

public class WinButton implements Button {}
public class WinBorder implements Border {}

// 接着实现工厂
public class MacFactory {
	public static Button createButton() {
	    return new MacButton();
	}
		public static Border createBorder() {
	    return new MacBorder();
	}
}
public class WinFactory {
	public static Button createButton() {
	    return new WinButton();
	}
		public static Border createBorder() {
	    return new WinBorder();
	}
}

 

3、单例模式(Singleton pattern)


单例模式,也叫单子模式,是一种常用的软件设计模式。

在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。

实现单例模式的思路是:一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。

单例模式在多线程的应用场合下必须小心使用。如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。 解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁(虽然这样会降低效率)。

代码举例

通常单例模式在Java中,有两种构建方式:

  • 懒汉方式。指全局的单例实例在第一次被使用时构建。
  • 饿汉方式。指全局的单例实例在类装载时构建。(static代码块中)

单例模式(饿汉模式)应用的例子如下述代码所示:

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
  
    // Private constructor suppresses   
    private Singleton() {}
 
    // default public constructor
    public static Singleton getInstance() {
        return INSTANCE;
    }
  }

单例模式(懒汉模式)应用的例子如下述代码所示 (此种方法只能用在JDK5及以后版本(注意 INSTANCE 被声明为 volatile),之前的版本使用“双重检查锁”会发生非预期行为:

public class Singleton {
    private static volatile Singleton INSTANCE = null;
  
    // Private constructor suppresses 
    // default public constructor
    private Singleton() {}
  
    //thread safe and performance  promote 
    public static  Singleton getInstance() {
        if(INSTANCE == null){
             synchronized(Singleton.class){
                 //when more than two threads run into the first null check same time, to avoid instanced more than one time, it needs to be checked again.
                 if(INSTANCE == null){ 
                     INSTANCE = new Singleton();
                  }
              } 
        }
        return INSTANCE;
    }
  }

 

4、建造者模式(Builder Pattern)


它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。

在以下情况使用生成器模式:

  • 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时;
  • 当构造过程必须允许被构造的对象有不同的表示时。

     参与者

  • Builder

    为创建一个Product对象的各个部件指定抽象接口。

  • ConcreteBuilder

    实现Builder的接口以构造和装配该产品的各个部件。

    定义并明确它所创建的表示。

     提供一个检索产品的接口

  • Director

    构造一个使用Builder接口的对象。

  • Product

    表示被构造的复杂对象。ConcreateBuilder创建该产品的内部表示并定义它的装配过程。

    包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

 UML用例图

代码举例

/**
 * Represents the product created by the builder.
 */
class Car {
    private int wheels;
    private String color;

    public Car() {
    }

    public String getColor() {
        return color;
    }

    public void setColor(final String color) {
        this.color = color;
    }

    public int getWheels() {
        return wheels;
    }

    public void setWheels(final int wheels) {
        this.wheels = wheels;
    }

    @Override
    public String toString() {
        return "Car [wheels = " + wheels + ", color = " + color + "]";
    }
}

/**
 * The builder abstraction.
 */
interface CarBuilder {
    Car build();

    CarBuilder setColor(final String color);

    CarBuilder setWheels(final int wheels);
}

class CarBuilderImpl implements CarBuilder {
    private Car car;

    public CarBuilderImpl() {
        car = new Car();
    }

    @Override
    public Car build() {
        return car;
    }

    @Override
    public CarBuilder setColor(final String color) {
        car.setColor(color);
        return this;
    }

    @Override
    public CarBuilder setWheels(final int wheels) {
        car.setWheels(wheels);
        return this;
    }
}

public class CarBuildDirector {
    private CarBuilder builder;

    public CarBuildDirector(final CarBuilder builder) {
        this.builder = builder;
    }

    public Car construct() {
        return builder.setWheels(4)
                      .setColor("Red")
                      .build();
    }

    public static void main(final String[] arguments) {
        final CarBuilder builder = new CarBuilderImpl();

        final CarBuildDirector carBuildDirector = new CarBuildDirector(builder);

        System.out.println(carBuildDirector.construct());
    }
}

 

5、原型模式(Prototype pattern)

原型模式是创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。

原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据。

UML

代码举例(浅复制)(更多是使用序列化和反序列化实现深复制,这个要看需求)

// Prototype pattern
public abstract class Prototype implements Cloneable {
    public Prototype clone() throws CloneNotSupportedException{
        return (Prototype) super.clone();
    }
}
	
public class ConcretePrototype1 extends Prototype {
    @Override
    public Prototype clone() throws CloneNotSupportedException {
        return (ConcretePrototype1)super.clone();
    }
}

public class ConcretePrototype2 extends Prototype {
    @Override
    public Prototype clone() throws CloneNotSupportedException {
        return (ConcretePrototype2)super.clone();
    }
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 设计模式是软件开发中常用的一种解决方案,它们是一些经过实践验证的可复用设计思想。设计模式允许开发人员在类和对象的结构上灵活地更改,并提供了一种优雅的解决方案来应对各种软件开发问题。 GOF(Gang of Four)是指Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位软件工程师,他们在《设计模式:可复用面向对象软件的基础》一书中总结了23种常见的设计模式,这本书因此而获得了“设计模式圣经”的称号。 这本书以案例为基础,深入浅出地讲解了每个设计模式的原理和应用场景,并提供了C++实现源码。 其中,创建设计模式包括单例模式、工厂方法模式、抽象工厂模式、建造者模式和原模式。这些模式都提供了一种方式来创建对象,使得程序在实例化对象时更加灵活和可扩展。 结构设计模式包括适配器模式、装饰器模式、代理模式、组合模式、享元模式和外观模式。这些模式关注如何通过类和对象的组合来创建更大的结构,并提供了一种优雅的方式来简化系统的复杂性。 行为设计模式包括策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式和中介者模式。这些模式关注对象之间的通信和交互,它们提供了一种优雅的方式来实现松耦合和可维护的代码。 总之,设计模式是软件开发中非常重要的一部分,它们提供了一种通用的解决方案来处理常见的设计问题。通过学习和应用设计模式,开发人员可以提高代码的可复用性、可扩展性和可维护性,并加快开发进度。 ### 回答2: 设计模式是软件开发中常用的解决问题的一种思维方式或者说是一种已被证实有效的解决问题的方法。GOF 23种设计模式是由四位著名的软件工程师提出并总结出的一套经典的设计模式GOF 23种设计模式分别是创建模式、结构模式和行为模式创建模式包括简单工厂模式、工厂方法模式、抽象工厂模式、单例模式、建造者模式和原模式。结构模式包括适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式和代理模式。行为模式包括策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式和解释器模式GOF 23种设计模式具有不同的应用场景和优势。通过学习和理解这些设计模式,开发者可以更加灵活地应对各种软件开发中的问题。同时,掌握这些设计模式也有助于提高代码的可读性、可维护性和可扩展性。 附带C语言实现源码是一种更加具体的学习和理解设计模式的方法。通过查看实现源码,可以更加直观地看到设计模式在实践中的应用。这些源码可以作为学习的参考,帮助开发者更好地理解设计模式的思想和使用方式。 总之,设计模式是软件开发中非常重要的一部分,通过学习GOF 23种设计模式并理解其应用场景和优势,可以提高软件开发的效率和质量。附带C语言实现源码能够更加具体地帮助开发者理解设计模式的实际应用。 ### 回答3: 设计模式是软件工程中常用的一种设计思想或模板,可以用于解决特定的问题和提供可重用的解决方案。GOF(Gang of Four)提出了23种设计模式,并在书籍《设计模式:可复用面向对象软件的基础》中进行了详细的解析和说明。 这本书详细地介绍了23种设计模式,包括创建模式、结构模式和行为模式。通过阅读这本书,读者可以了解每种设计模式的特点、适用场景和实现方法。另外,书中还通过示例代码的方式演示了每种设计模式的具体实现,并提供了附带的C语言实现源码。 这本书对于理解设计模式的概念和思想非常有帮助。它不仅提供了23种设计模式的名字和简介,还详细解释了每种模式的适用场景和应用案例。读者可以通过学习这些设计模式,了解如何将它们应用于自己的软件开发工作中,提高代码的可重用性和可维护性。 书中的C语言实现源码是帮助读者理解和实践设计模式的重要资源。通过阅读源码,读者可以更加深入地理解每种设计模式的具体实现细节,并进一步提升自己的编程能力。 总之,通过学习《设计模式:可复用面向对象软件的基础》这本书,读者可以全面了解设计模式的概念、分类和实现方法,并通过阅读附带的C语言实现源码来加深对设计模式的理解和应用。这将对提升软件设计和开发的能力和水平非常有帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

济南大飞哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值