GOF 23种常用设计模式

一、创建型模式

1.原型模式

动机

在软件系统种,经常存在着某些结构复杂的对象的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但他们却拥有比较稳定的一致的接口

如何应对变化?如何向客户端隔离出这些易变的对象,从而使得依赖这些易变对象的客户程序不会随着需求的变化而变化?

UML类图

在这里插入图片描述

代码实现
import java.io.*;

public abstract class Prototype implements Serializable,Cloneable {

    public Prototype deepClone() throws IOException, ClassNotFoundException {
        //将对象写入流中,
        ByteArrayOutputStream bao = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bao);
        oos.writeObject(this);
        //将对象取出来
        ByteArrayInputStream bi = new ByteArrayInputStream(bao.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bi);
        return (Prototype)ois.readObject();
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ConcretePrototype concretePrototype = new ConcretePrototype();
        Prototype prototype = concretePrototype.deepClone();
        System.out.println(concretePrototype);
        System.out.println(prototype);
        System.out.println(concretePrototype.getClass().getName());
        System.out.println(prototype.getClass().getName());
    }
}



class ConcretePrototype extends Prototype{

}

2.单例模式

动机

在软件系统种,经常存在着某些特殊的类,必须保证他们在系统中只有一个实例,才能确保逻辑的正确性或良好的效率

如何绕过常规的构造器,提供一个机制来保证一个类只有一个实例?这是设计者的责任,而不是客户端程序员的责任

UML类图

在这里插入图片描述

代码实现

(1)饿汉式

//饿汉模式:线程安全,耗费资源。
public class HugerSingletonTest {
    //该对象的引用不可修改
    private static final HugerSingletonTest ourInstance = new HugerSingletonTest();

    public static HugerSingletonTest getInstance() {
        return ourInstance;
    }

    private HugerSingletonTest() {}
}

(2)懒汉式

public class Singleton {
    private static Singleton ourInstance;

    public static Singleton getInstance() {
        if (null == ourInstance) {
            synchronized (Singleton.class) {
                if (null == ourInstance) {
                    ourInstance = new Singleton();
                }
            }
        }
        return ourInstance;
    }

    private Singleton() {}
}

(3)静态内部类

public class Singleton {
    private static class SingletonHodler {
        private static final Singleton ourInstance = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHodler.ourInstance;
    }

    private Singleton() {}
}

(4)枚举

enum SingletonTest {  
    INSTANCE;  
    public void whateverMethod() {
        
    }
}
开发实例
package com.utils;
/**
 * Created by xsl on 2020/7/31 10:57
 */
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
/**
 * @ClassName ThreadPool
 * @Description: 线程池 单例与代理模式
 * @Author xsl
 * @Date 2020/7/31 10:57
 **/
public class ThreadPool {
    /**
     * 初始化核心线程数
     */
    private static final int processors = Runtime.getRuntime().availableProcessors();

    /**
     * 线程池最大容量
     */
    private static int maxPoolSize = processors * 2;

    /**
     * 扩容线程数闲置寿命
     */
    private static int keepAliveTime = 2;

    /**
     * 等待队列长度
     */
    private static int waitQueueSize = 1000;

    /**
     * 拒绝策略
     */
    private static RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

    /**
     * 线程池实例,懒汉式
     */
    private static ThreadPool instance = null;

    /**
     * 可重用锁
     */
    private static ReentrantLock lock = new ReentrantLock();

    /**
     * 线程池
     */
    private static ExecutorService fixedThreadPool = null;

    private ThreadPool() {
        //私有构造器
    }

    public ExecutorService getExecutorService() {
        return fixedThreadPool;
    }
    public static ThreadPool getInstance() {
        //双重判断加锁
        if (instance == null) {
            lock.lock();
            if (instance == null) {
                instance = new ThreadPool();
                //使用ThreadPoolExecutor不要使用Executors
                fixedThreadPool = new ThreadPoolExecutor(
                        processors,
                        maxPoolSize,
                        keepAliveTime,
                        TimeUnit.SECONDS,
                        new LinkedBlockingQueue<Runnable>(waitQueueSize),
                        Executors.defaultThreadFactory(),
                        handler
                );
            }
            lock.unlock();
        }
        return instance;
    }
}

3.工厂方法

动机

在软件系统中,经常面临着创建的对象(或绑定的对象)发生需求的变化,所以期望统一套代码通过动态绑定的形式来抵抗这样的变化

UML类图

在这里插入图片描述

代码实现
interface Factory{
    Product createProduct();
}


interface Product{

}

class ConcreteProduct1 implements Product{

}

class ConcreteFactory1 implements Factory{

    @Override
    public Product createProduct() {
        return new ConcreteProduct1();
    }
}

4.抽象工厂

动机

在抽象工厂是工厂方法的一个扩展,当我们要创建的对象不止一个,且这些对象还是成套出现的时候,我们就必须要使用某种方式对这样的成套就行约束

UML类图

在这里插入图片描述

代码实现
interface Factory{
    Product1 createProduct1();
    
    Product2 createProduct2();
}


interface Product1{

}

interface Product2{
    
}

class ConcreteProduct1 implements Product1{

}

class ConcreteProduct2 implements Product2{

}

class ConcreteFactory1 implements Factory{

    @Override
    public Product1 createProduct1() {
        return new ConcreteProduct1();
    }

    @Override
    public Product2 createProduct2() {
        return new ConcreteProduct2();
    }
}

5.建造者模式

动机

在软件系统中,有时候面临着一个复杂对象的创建工作,其通常用各个部分的子对象用一定算法构成,由于需求的变化,这个复杂对象的内部经常面临着剧烈的变化,但将他们组合在一起的算法却相对稳定的时候适合使用建造者模式

UML类图

在这里插入图片描述

代码实现
class Product{
    private String partA;
    private String partB;
    private String partC;

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    public void setPartC(String partC) {
        this.partC = partC;
    }
}


abstract class Builder{
    protected Product product = new Product();

    public abstract void createPartA();
    public abstract void createPartB();
    public abstract void createPartC();

    public Product getProduct(){
        return product;
    }
}

class ConcreteBuilder extends Builder{

    @Override
    public void createPartA() {
        product.setPartA("A");
    }

    @Override
    public void createPartB() {
        product.setPartA("A");
    }

    @Override
    public void createPartC() {
        product.setPartA("A");
    }
}


class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public Product createProduct(){
        builder.createPartA();
        builder.createPartB();
        builder.createPartC();
        return builder.getProduct();
    }
}

二、结构型模式

1.代理模式

动机

对象增强、权限隔离,方法改写等,代理模式的用途很广泛

UML类图

在这里插入图片描述

代码实现

(1)静态代理

interface Subject{
    public void request();
}


class RealSubject implements Subject{

    @Override
    public void request() {
        System.out.println("aaa");
    }
}

class Proxy implements Subject{

    private RealSubject realSubject = new RealSubject();

    @Override
    public void request() {
        //某些操作或直接改写某些方法
        realSubject.request();
        //某些操作
    }
}

(2)jdk动态代理

public class A {

    public static void main(String[] args) {
        ProxyObject proxy = new ProxyObject(new RealSubject());
        Subject subject = (Subject)Proxy.newProxyInstance(
                RealSubject.class.getClassLoader(),
                RealSubject.class.getInterfaces(),
                proxy
        );
        subject.request();
    }
}

interface Subject{
    public void request();
}


class RealSubject implements Subject{

    @Override
    public void request() {
        System.out.println("aaa");
    }
}

class ProxyObject implements InvocationHandler {

    private Object target;

    public ProxyObject(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("aaa");
        Object retVal = method.invoke(target, args);
        return retVal;
    }
}

(3)Cglib动态代理

cglib动态代理需要引入依赖

<dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib</artifactId>
   <version>3.3.0</version>
</dependency>
public class A{
	public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Subject.class);
        enhancer.setCallback(new LogInterceptor());
        Subject subject = (Subject)enhancer.create();
        subject.request();
    }
}


class Subject{
    public void request(){
        System.out.println("aaa");
    }
}


class LogInterceptor implements MethodInterceptor {

    /**
     *
     * @param obj 表示要进行增强的对象
     * @param method 表示拦截的方法
     * @param objects 数组表示参数列表,基本数据类型需要传入其包装类型,如int-->Integer、long-Long、double-->Double
     * @param methodProxy 表示对方法的代理,invokeSuper方法表示对被代理对象方法的调用
     * @return 执行结果
     * @throws Throwable 异常
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before(method.getName());
        // 注意这里是调用invokeSuper而不是invoke,否则死循环;
        // methodProxy.invokeSuper执行的是原始类的方法;
        // method.invoke执行的是子类的方法;
        Object result = methodProxy.invokeSuper(obj, objects);
        after(method.getName());
        return result;
    }

    /**
     * 调用invoke方法之前执行
     */
    private void before(String methodName) {
        System.out.println("调用方法" + methodName +"之【前】的日志处理");
    }

    /**
     * 调用invoke方法之后执行
     */
    private void after(String methodName) {
        System.out.println("调用方法" + methodName +"之【后】的日志处理");
    }
}

(3)jassist动态代理

这个更牛,简直无所不能,怎么实现代理模式自行百度吧,这里展示它的强大之处

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.20.0-GA</version>
</dependency>
public static void main(String[] args) throws CannotCompileException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, NotFoundException {
        // 创建类
        ClassPool pool = ClassPool.getDefault();
        CtClass cls = pool.makeClass("cn.ibm.com.TestClass");

        // 添加私有成员name及其getter、setter方法
        CtField param = new CtField(pool.get("java.lang.String"), "name", cls);
        param.setModifiers(Modifier.PRIVATE);
        cls.addMethod(CtNewMethod.setter("setName", param));
        cls.addMethod(CtNewMethod.getter("getName", param));
        cls.addField(param, CtField.Initializer.constant(""));

        // 添加无参的构造体
        CtConstructor cons = new CtConstructor(new CtClass[] {}, cls);
        cons.setBody("{name = \"Brant\";}");
        cls.addConstructor(cons);

        // 添加有参的构造体
        cons = new CtConstructor(new CtClass[] {pool.get("java.lang.String")}, cls);
        cons.setBody("{$0.name = $1;}");
        cls.addConstructor(cons);

        // 打印创建类的类名
        System.out.println(cls.toClass());

        // 通过反射创建无参的实例,并调用getName方法
        Object o = Class.forName("cn.ibm.com.TestClass").newInstance();
        Method getter = o.getClass().getMethod("getName");
        System.out.println(getter.invoke(o));

        // 调用其setName方法
        Method setter = o.getClass().getMethod("setName", new Class[] {String.class});
        setter.invoke(o, "Adam");
        System.out.println(getter.invoke(o));

        // 通过反射创建有参的实例,并调用getName方法
        o = Class.forName("cn.ibm.com.TestClass").getConstructor(String.class).newInstance("Liu Jian");
        getter = o.getClass().getMethod("getName");
        System.out.println(getter.invoke(o));
    }

2.适配器模式

动机

将一个现有对象放在新环境中使用,但是现有对象并不能完全满足该新环境场景

UML类图

在这里插入图片描述

代码实现
public class A {

    public static void main(String[] args) {
        TargetAdapter targetAdapter = new TargetAdapter(new Adapter());
        targetAdapter.request();
    }
}

interface Target{
    void request();
}

class Adapter{
    void specificRequest() {
        System.out.println("适配者中的业务代码被调用!");
    }
}

class TargetAdapter implements Target{

    private Adapter adapter;

    public TargetAdapter(Adapter adapter) {
        this.adapter = adapter;
    }

    @Override
    public void request() {
        adapter.specificRequest();
    }
}

3.桥接模式

动机

某个类型有多个维度的变化,如何应对这种多个维度的变化,使用面向对象的技术使得类型可以沿着多个方向发生变化

UML类图

在这里插入图片描述

代码实现
public class A {
    public static void main(String[] args) {
        HuaWei huaWei = new HuaWei(new OnlineSale());
        huaWei.make();
    }
}


abstract class Computer{
    protected Sale sale;

    public Computer(Sale sale) {
        this.sale = sale;
    }

    abstract void make();
}

class HuaWei extends Computer{

    public HuaWei(Sale sale) {
        super(sale);
    }

    @Override
    void make() {
        System.out.println("制造华为");
        sale.sale();
    }


}

interface Sale{
    void sale();
}

class OnlineSale implements Sale{

    @Override
    public void sale() {
        System.out.println("线上销售");
    }
}

class Offline implements Sale{

    @Override
    public void sale() {
        System.out.println("线下销售");
    }
}

4.装饰器模式

动机

在某些情况下我们会过度使用继承来扩展对象的功能,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多,各种子类的组合会导致子类的膨胀

如何使对象功能的扩展能根据需要的动态来实现?同时避免扩展功能的增多带来的子类膨胀问题?从而使得任何功能扩展变化所导致的影响最低?

UML类图

在这里插入图片描述

代码实现
public class DecoratorPattern {

    interface Stream{

        /**
         * 读
         */
        void read();


        /**
         * 写
         */
        void write();
    }


    class FileStream implements Stream{
        @Override
        public void read() {
            //实现
        }

        @Override
        public void write() {
            //实现
        }
    }


    /**
     * 装饰器
     */
    class BufferStream implements Stream{

        Stream stream;

        public BufferStream(Stream stream) {
            this.stream = stream;
        }

        @Override
        public void read() {
            //缓冲处理
            stream.read();
        }

        @Override
        public void write() {
            //缓冲处理
            stream.write();
        }
    }
}

5.外观模式

动机

外观模式又叫作门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

UML类图

在这里插入图片描述

代码实现
public class A {
    public static void main(String[] args) {
        Facade facade = new Facade();
        facade.method();
    }
}


class Facade{
    private System1 system1 = new System1();
    private System2 system2 = new System2();
    private System3 system3 = new System3();

    public void method(){
        system1.operation();
        system2.operation();
        system3.operation();
    }

}


class System1{
    public void operation(){
        System.out.println("System1");
    }
}


class System2{
    public void operation(){
        System.out.println("System2");
    }
}


class System3{
    public void operation(){
        System.out.println("System3");
    }
}

6.享元模式

动机

在软件系统中采用纯粹对象的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价

某些对象本来可以被重复利用,可能频繁的创建和销毁会对系统有性能损耗

UML类图

在这里插入图片描述

代码实现
public class FlyweightPattern {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight f01 = factory.getFlyweight("a");
        Flyweight f02 = factory.getFlyweight("a");
        Flyweight f03 = factory.getFlyweight("a");
        Flyweight f11 = factory.getFlyweight("b");
        Flyweight f12 = factory.getFlyweight("b");
        f01.operation(new UnsharedConcreteFlyweight("第1次调用a。"));
        f02.operation(new UnsharedConcreteFlyweight("第2次调用a。"));
        f03.operation(new UnsharedConcreteFlyweight("第3次调用a。"));
        f11.operation(new UnsharedConcreteFlyweight("第1次调用b。"));
        f12.operation(new UnsharedConcreteFlyweight("第2次调用b。"));
    }
}
//非享元角色
class UnsharedConcreteFlyweight {
    private String info;
    UnsharedConcreteFlyweight(String info) {
        this.info = info;
    }
    public String getInfo() {
        return info;
    }
    public void setInfo(String info) {
        this.info = info;
    }
}
//抽象享元角色
interface Flyweight {
    public void operation(UnsharedConcreteFlyweight state);
}
//具体享元角色
class ConcreteFlyweight implements Flyweight {
    private String key;
    ConcreteFlyweight(String key) {
        this.key = key;
        System.out.println("具体享元" + key + "被创建!");
    }
    public void operation(UnsharedConcreteFlyweight outState) {
        System.out.print("具体享元" + key + "被调用,");
        System.out.println("非享元信息是:" + outState.getInfo());
    }
}
//享元工厂角色
class FlyweightFactory {
    private HashMap<String, Flyweight> flyweights = new HashMap<String, Flyweight>();
    public Flyweight getFlyweight(String key) {
        Flyweight flyweight = (Flyweight) flyweights.get(key);
        if (flyweight != null) {
            System.out.println("具体享元" + key + "已经存在,被成功获取!");
        } else {
            flyweight = new ConcreteFlyweight(key);
            flyweights.put(key, flyweight);
        }
        return flyweight;
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答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语言实现源码来加深对设计模式的理解和应用。这将对提升软件设计和开发的能力和水平非常有帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值