资讯专栏INFORMATION COLUMN

设计模式--简化解释(一)——创建型设计模式

iKcamp / 2648人阅读

摘要:维基百科在软件工程中,创建型设计模式是用于解决对象创建机制,尝试在指定场景下使用合理的方式来创建对象的设计模式。维基百科说建造者模式是一种对象创建软件设计模式,其目的是找到一种解决方案,以解决可伸缩构造函数的反模式。

1.创建型设计模式
2.结构型设计模式
3.行为型设计模式

创建型设计模式

简而言之

创建型设计模式关注的是如何实例化一个或者一组相关的对象。

维基百科

在软件工程中,创建型设计模式是用于解决对象创建机制,尝试在指定场景下使用合理的方式来创建对象的设计模式。基本的创建方式对导致设计问题或者增加设计的复杂度。创建型设计模式通过一些控制对象创建的手段来解决这些问题。
? 简单工厂

现实例子

考虑一下,你需要建造一个房子,然后需要几扇门。如果每次需要一扇门的时候,你都穿上木匠的衣服然后在房间里左门会造成很大的混乱。取而代之是你需要买一个从工厂里做好的。

简而言之

对客户端来说,简单工厂模式仅仅生成一个实例,不需要暴露给客户端人户实例化的逻辑。

维基百科说

在面向对象编程中(OOP),工厂是一个用于创建对象的对象,正式的工厂是一个方法或者函数,在某些方法调用的时候返回不同的原型或者对象,我们认为这个对象是新的。

编程实例
首先我们有一个们的接口和实现

public interface Door {
    float getWidth();
    float getHeight();
}
public class WoodenDoor implements Door {
    private float width;
    private float height;

    public WoodenDoor(float width, float height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public float getWidth() {
        return 0;
    }

    @Override
    public float getHeight() {
        return 0;
    }
}

然后我们需要一个生产并返回门的工厂

public class DoorFactory {
    public static Door makeDoor(float width,float height)
    {
        return new WoodenDoor(width,height);
    }
}

使用方式如下

Door door = DoorFactory.makeDoor(1200L,2100L);
System.out.println("Door Width:"+door.getWidth());
System.out.println("Door Height:"+door.getHeight());

何时使用
当创建一个不仅仅是几条赋值语句同时包含一些逻辑的对象的时候,把创建对象的代码放到一个专用的工厂中而不是到处赋值相同的代码,这是情理之中的。

? 工厂方法

现实例子

考虑一个人事部经理的例子. 不可能所有的岗位都有一个人来面试. 根据职位空缺,他将面试的步骤安排给不同的人.

简而言之

提供一种将实例化逻辑委托给子类的方式.

维基百科说

在给予类的编程中,工厂方法模式是一个创建型的模式,这个模式用于解决建对象的问题而无需指定要创建的精确的类。通过调用工厂方法(在接口中指定并由子类实现,或者在基类中实现),或者通过派生类(而不是调用构造函数)来实现,这是通过创建对象来完成的。

编程示例
参考上边人事部经理的例子。首先我们有一个面试官的接口和一些实现。

public interface Inteviewer {
    void askQuestions();
}
public class Developer implements Inteviewer {
    @Override
    public void askQuestions() {
        System.out.println("Ask about Design Patterns");
    }
}
public class CommunityExecutive implements Inteviewer {
    @Override
    public void askQuestions() {
        System.out.println("Ask about community build");
    }
}

现在我们创建 HiringManager

public abstract class HiringManager {
    protected abstract Inteviewer makeInteviewer();

    public void takeInteview()
    {
        Inteviewer inteviewer = makeInteviewer();
        inteviewer.askQuestions();
    }
}

现在和人子类都可以实现该类来提供需要的面试官

public class DevelopmentManager extends HiringManager {
    @Override
    protected Inteviewer makeInteviewer() {
        return new Developer();
    }
}
public class CommunityManager extends HiringManager {
    @Override
    protected Inteviewer makeInteviewer() {
        return new CommunityExecutive();
    }
}

使用举例

public class Client {
    public static void main(String[] args) {
        HiringManager manager = new DevelopmentManager();
        manager.takeInteview();

        manager = new CommunityManager();
        manager.takeInteview();
    }
}

何时使用?
当一个类中有一些通用的处理但是子类需要在运行时决定的时候使用。换句话说,客户端不知道需要的精确的子类。

? 抽象工厂

现实举例

扩展我们的简单工厂模式的门的例子。考虑到你的需求,你可能从一个木门的商店购买一个木门,从一个铁门的商店购买一个铁门,或者从另外的相关的商店购买一个PVC门。除此之外你可能需要一个有不同技能的伙计帮你装门,例如木匠来装木门,焊接工装铁门。正如你看到的那样,现在门之间有一个依赖,木门需要木匠,铁门需要焊接工等等。

简而言之

一个工厂的工厂。一个工厂在不指定具体的类的情况下将独立但相关的工程组合在一起。

维基百科说

抽象工厂模式提供了一种方式来封装一度独立的工厂,这些工厂有相同的主题当时没有指定具体的类。

编程示例

翻译上边门的例子. 首先我们有门的接口和几个门的实现

public interface Door {
    String getDescription();
}
public class WoodenDoor implements Door {
    @Override
    public String getDescription() {
        return "I am a wooden door";
    }
}
public class IronDoor implements Door {
    @Override
    public String getDescription() {
        return "I am an iron door";
    }
}

然后每一种门我们有一些安装专家

public interface DoorFittingExpert {
    String getDescription();
}
public class Carpenter implements DoorFittingExpert {
    @Override
    public String getDescription() {
        return "I can only fit wooden doors";
    }
}
public class Welder implements DoorFittingExpert {
    @Override
    public String getDescription() {
        return "I can only fit iron doors";
    }
}

现在我们需要一个抽象工厂来帮我们决定相关对象的族。例如木门工厂需要生产木门和木门安装专家,铁门工厂需要生产铁门和铁门安装专家。

public interface DoorFactory {
    Door makeDoor();
    DoorFittingExpert makeFittingExper();
}
public class WoodenDoorFactory implements DoorFactory {
    @Override
    public Door makeDoor() {
        return new WoodenDoor();
    }

    @Override
    public DoorFittingExpert makeFittingExper() {
        return new Carpenter();
    }
}
public class IronDoorFactory implements DoorFactory {
    @Override
    public Door makeDoor() {
        return new IronDoor();
    }

    @Override
    public DoorFittingExpert makeFittingExper() {
        return new Welder();
    }
}

使用方式如下:

DoorFactory doorFactory = new WoodenDoorFactory();
        Door door = doorFactory.makeDoor();
        DoorFittingExpert expert = doorFactory.makeFittingExper();
        System.out.println("Door:"+door.getDescription());
        System.out.println("Expert:"+expert.getDescription());

正如上边看到的一样,木门工厂封装了carpenterwooden door,铁门工厂封装了iron doorwelder.因此工厂帮我们确信每一个创建的门都不会有错误的安装的专家

何时使用
当有相关的复杂的创建逻辑的依赖的时候

? 建造者

现实举例

设想一下你在Hardee,你要点餐,我们会说:Big Hardee,他们不会问任何问题就会把饭端过来。这是一个简单工厂的例子。但是有种情况下创建逻辑包含几个步骤。例如你想吃一个自助的Subway,汉堡怎么做,例如面包用什么样的,用什么样的酱汁,想要什么样的奶酪。这种情况下,建造者模式将会拯救我们。

简而言之

避免构造函数污染的情况下为对象创造不同的特性。当一个对象有多个特性或者创建对象包含几个步骤的时候使用。

维基百科说

建造者模式是一种对象创建软件设计模式,其目的是找到一种解决方案,以解决可伸缩构造函数的反模式。

说道这里,让我添加一点关于伸缩构造函数反模式的内容。在某些地方,我们都看到了如下的构造函数。:

public Deal(int size, boolean cheese ,boolean pepperoni, boolean tomato, boolean lettuce)
{
}

正如你所看到的;构造函数参数的数量很快就会失去控制,并且很难理解参数的排列。另外,如果你想在未来增加更多的选项,这个参数列表还可以继续增长。这被称为伸缩构造函数反模式。

程序示例
明智的选择是使用建造者模式。首先我们要有一个我们要做的汉堡(burger)

package com.suifeng.designpattern.builder;

public class Burger {
    private int size;
    private boolean cheese;
    private boolean pepperoni;
    private boolean lettuce;
    private boolean tomato;

    public Burger(BurgerBuilder builder)
    {
        this.size = builder.size;
        this.cheese=builder.cheese;
        this.pepperoni = builder.pepperoni;
        this.lettuce = builder.lettuce;
        this.tomato = builder.tomato;
    }

    @Override
    public String toString() {
        return "Burger{" +
                "size=" + size +
                ", cheese=" + cheese +
                ", pepperoni=" + pepperoni +
                ", lettuce=" + lettuce +
                ", tomato=" + tomato +
                "}";
    }

    static class BurgerBuilder{
        private int size;
        private boolean cheese;
        private boolean pepperoni;
        private boolean lettuce;
        private boolean tomato;

        public BurgerBuilder(int size) {
            this.size = size;
        }

        public BurgerBuilder addCheese()
        {
            this.cheese = true;
            return this;
        }

        public BurgerBuilder addPepperoni()
        {
            this.pepperoni = true;
            return this;
        }

        public BurgerBuilder addLettuce()
        {
            this.lettuce = true;
            return this;
        }

        public BurgerBuilder addTomato()
        {
            this.tomato = true;
            return this;
        }

        public Burger build()
        {
            return new Burger(this);
        }
    }
}

使用方式如下

Burger burger = new Burger.BurgerBuilder(12).addCheese().addLettuce().build();
        System.out.println(burger);

何时使用
当一个对象有几个特性并且需要避免构造器伸缩。与工厂模式的主要不同是:工厂模式的创建过程只有一个步骤而建造者模式需要多个步骤。

? 原型

现实举例

还记得多里吗?就是那只被克隆的山羊。我们不关注细节,这里的关键就是克隆。

简而言之

通过克隆的方式根据现有对象来创建新对象

维基百科说

原型模式是软件开发中的一个创建型设计模式。当要创建的对象类型由一个原型实例决定时,使用原型模式,该实例被克隆以产生新的对象。

简而言之,它允许您创建一个现有对象的副本,并根据您的需要修改它,而不是从头开始创建一个对象并设置它。

Programmatic Example

Java中可以使用clone方法

public class Sheep implements Cloneable {

    private String name;
    private String category;

    public Sheep(String name, String category) {
        this.name = name;
        this.category = category;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    @Override
    public String toString() {
        return "Sheep{" +
                "name="" + name + """ +
                ", category="" + category + """ +
                "}";
    }

    public Sheep clone()
    {
        Object obj = null;

        try {
            obj =super.clone();

            return (Sheep) obj;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return null;
    }
}

克隆方式如下

public class Client {
    public static void main(String[] args) {
        Sheep sheep = new Sheep("Jolly","Mountain Sheep");

        Sheep dolly = sheep.clone();
        dolly.setName("Dolly");

        System.out.println(dolly);
    }
}

何时使用?

当需要的对象与存在的对象相似的时候或者相比于克隆创建成本比较高的情况.

? 单例

现实举例

同一时间一个国家只有一个总统。 当指责需要的时候,采取行动的是同一个总统. 在这里总统就是单例的

简而言之

一个特定的类确保只创建一个对象。

维基百科说

在软件工程中,单例模式是一种软件设计模式,它将类的实例化限制为一个对象。 当需要一个对象来协调整个系统中的操作时,这很有用。

单例模式实际上被认为是一种反模式,应该避免过度使用。它并不一定是坏的,并且可以有一些有效的用例,但是应该谨慎使用,因为它在您的应用程序中引入了一个全局状态,并且在一个地方对它进行更改可能会影响到其他领域,因此调试可能变得非常困难。另一件不好的事情是,它使您的代码紧密耦合,另外对单例对象的模拟是困难的。

编程示例
创建一个单例,需要将构造函数私有,禁用可控和扩展,通过创建一个静态的变量来保存实例。

public class President {
    private static President INSTANCE ;

    private President()
    {

    }

    public static President getInstance()
    {
        if(INSTANCE == null)
        {
            INSTANCE = new President();
        }

        return INSTANCE;
    }


}

使用方式如下

 President president1 = President.getInstance();
        President president2 = President.getInstance();

        System.out.println(president1 == president2);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71029.html

相关文章

  • PHP 设计模式概述

    摘要:创建型模式主要有以下五种简单工厂模式和工厂方法模式抽象工厂模式单例模式建造者模式原型模式在设计模式一书中将工厂模式分为两类工厂方法模式与抽象工厂模式。 一、 设计模式(Design pattern)是什么 设计模式是一套被反复使用、多数人知晓、经过分类编目的代码设计的经验总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 二、 为什么会有设计模式 在软件开发过...

    IntMain 评论0 收藏0
  • 设计模式--简化解释(三)——行为模式

    摘要:创建型设计模式结构型设计模式行为型设计模式行为型设计模式简而言之行为型设计模式关心的是对象之间的责任分配。这种模式被认为是一种行为模式,因为它可以改变程序的运行行为。 1.创建型设计模式2.结构型设计模式3.行为型设计模式 行为型设计模式 简而言之 行为型设计模式关心的是对象之间的责任分配。它们与结构模式的不同之处在于,它们不仅指定了结构,而且还概述了它们之间消息传递/通信的模式。换句...

    cangck_X 评论0 收藏0
  • 设计模式--简化解释(二)——结构设计模式

    摘要:创建型设计模式结构型设计模式行为型设计模式结构型设计模式简而言之结构模式主要涉及对象的组成,或者是实体如何相互使用。 1.创建型设计模式2.结构型设计模式3.行为型设计模式 结构型设计模式 简而言之 结构模式主要涉及对象的组成,或者是实体如何相互使用。或者,另一个解释是,他们帮助回答如何构建一个软件组件? 维基百科说 在软件工程中,结构设计模式是通过识别实体之间关系的简单方法来简化设计...

    miya 评论0 收藏0
  • 《JavaScript设计模式》读后感 觉很复杂

    摘要:想继续了解设计模式必须要先搞懂面向对象编程,否则只会让你自己更痛苦。创建型设计模式主要有简单工厂模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式和单例模式,下面一一道来。而工厂方法模式本意是将实际创建对象的工作推迟到子类中。 接触前端两三个月的时候,那时候只是听说设计模式很重要,然后我就去读了一本设计模式的书,读了一部分,也不知道这些设计模式到底设计出来干嘛的,然后就没再看了。后...

    e10101 评论0 收藏0
  • 记录些用来学习设计模式的博客及书籍:

    摘要:里氏代换原则里氏代换原则面向对象设计的基本原则之一。里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。里氏代换原则是对开闭原则的补充。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。 一、设计模式的六大原则: 1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不...

    NSFish 评论0 收藏0

发表评论

0条评论

iKcamp

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<