设计模式 - 5种创建型模式

什么是设计模式?

设计模式就是套路,是被坑了N遍之后总结出来的经验。项目中合理的运用设计模式可以巧妙的解决很多问题。当然设计模式也不是万能的,根据项目需要来使用,不要为了设计模式而做项目,这样做出来的项目太虚伪。

什么样的代码才算是优秀的代码?有人说清晰的逻辑关系,明确的注释,符合八荣八耻就是好代码。能写出这样的代码,只能说明你有好的编码习惯,不代表写出来的代码就是优秀的代码。优秀的代码必须符合高内聚低耦合原则,写代码是要考虑扩展性、依赖性、单一性,用最少的代码做最多的事情。

设计模式 - 七大原则

开闭原则(Open Close Principle)
对扩展开放,对修改关闭,为了使程序的扩展性好,易于维护和升级。

里氏代换原则(Liskov Substitution Principle)
只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为,对实现抽象化的具体步骤的规范。

依赖倒转原则(Dependence Inversion Principle)
针对接口编程,而不是针对实现类编程,降低模块间的耦合。简单的说里氏代换原则和依赖倒转原则说的是一回事,只是角度不同,依赖倒置更偏向于客户

接口隔离原则(Interface Segregation Principle)
针对不同的功能,我们应该拆成多个接口,为了提高程序设计灵活性

迪米特法则(最少知道原则)(Demeter Principle)
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立,降低类之间的耦合,减少对其他类的依赖

单一职责原则( Single responsibility principle )
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因,为了降低类的复杂性,提高可读性可维护性

合成复用原则( Single responsibility principle )
能引用的不继承,提高职责类内部高聚合

这7个原则可以进行分类

理念层次:开闭原则
设计层次:单一职责、接口隔离、里氏替换原则(本层针对结构设计)
使用者层次:依赖倒置、迪米特法则(本次趋于实现层次)
代码层次:合成复用原则
在平时工作中都可以找到层次理念原型

设计模式分类
创建型

创建型模式,共5种:单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式

单例模式

单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。当一个类在运行时只有一个实例时我们称之为单例模式。那么单例模式有哪些实现?总体来说有三种思路:加载时初始化、利用枚举构造函数默认加载、内部加锁保证对象初始化一次

实体类

class Moon {
    。。。
}

方式一、加载即初始化

class SingleMoon1 {
    private static final Moon moon = new Moon();
    static Moon getInstance(){
        return moon;
    }
}

这种思路,又可以拆分为静态属性、静态代码块、静态内部类等方式加载即初始化

方式二、多线程只创建一次

class SingleMoon2 {
    private static volatile Moon moon;
    static Moon getInstance(){
        if (moon == null) {
            synchronized (SingleMoon2.class) {
                if (moon == null) {
                    moon = new Moon();
                }
            }
        }
        return moon;
    }
}

这种思路,可以拆分成两种,一种方法上同步,一种双重判断锁+volatile修饰

方式三、通过特殊类

enum SingleMoon3 {
    任意;
    Moon moon;
    private SingleMoon3() {
        moon = new Moon();
    }
    Moon getInstance(){
        return moon;
    }
}

枚举类的构造函数只会调用一次,利用这个特性获得单例对象。

原型模式

原型模式是用于创建重复的对象,同时又能保证性能。哪些时候可以使用原型模式?1、创建对象代价很大时(要调用一堆开销很大的方法或逻辑),2、不想使用构造函数,3、需要的对象跟原对象差不多只有少量属性需要修改
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆,在内存中对这个对象进行拷贝,要比直接new这个对象性能要好很多。

比方说我写了一篇博客,先发到CSDN,然后发到了公众号,我需要写两遍了?显然不需要,只需要拷贝一份就行,然后改下格式

public class Book implements Cloneable {
    public Book() {
        System.out.println("博客头。。。");
        System.out.println("博客第一行。。。");
        System.out.println("博客第N行。。。");
        System.out.println("博客结尾。。。");
    }
    @Override
    protected Book clone() throws CloneNotSupportedException {
        return (Book) super.clone();
    }
    public static void main(String[] args) throws CloneNotSupportedException {
        Book book = new Book();
        Book book1 = book.clone();
        System.out.println("CSDN" + book);
        System.out.println("公众号" + book1);
    }
}

打印​

博客头。。。
博客第一行。。。
博客第N行。。。
博客结尾。。。
CSDNcom.user.mode.Book@330bedb4
公众号com.user.mode.Book@2503dbd3

这里创建了两个对象,确只调用了一次构造函数

工厂模式(包含简单工厂模式、工厂方法模式、抽象工厂模式)

工厂顾名思义就是创建产品,根据是具体产品还是具体工厂可分为简单工厂模式和工厂方法模式,根据工厂的抽象程度可分为工厂方法模式和抽象工厂模式。其中简单工厂类图跟策略模式类图几乎一样,区别在于一个在服务端创建产品,一个在客户端创建产品。

简单工厂

简单工厂只有三种角色:工厂类角色、抽象产品角色、具体产品角色
缺点:所有产品都在一个工厂生产,产品增加需要修改工厂

public class TestMain {
    public static void main(String[] args) {
        PenFactory factory = new PenFactory();
        Pen pen = factory.produce("pencil");
        pen.show();
    }
}

抽象产品角色

abstract class Pen {
    abstract void show();
}

具体产品铅笔

class pencil extends Pen {
    @Override
    void show() {
        System.out.println("铅笔");
    }
}

具体产品毛笔

class WritingBrush extends Pen {
    @Override
    void show() {
        System.out.println("毛笔");
    }
}

工厂角色

class PenFactory {
    Pen produce(String ProductName) {
        switch (ProductName){
            case "pencil":
                return new pencil();
            case "WritingBrush":
                return new WritingBrush();
            default:
                return null;
        }
    }
}
工厂方法模式

工厂方法模式有4种角色:抽象工厂角色、具体工厂角色、抽象产品角色、具体产品角色
缺点:产品种类非常多的时候,会工厂爆炸,维护工厂代价很高

public class TestMain {
    public static void main(String[] args) {
        IPenFactory factory1 = new PenFactory1();
        Pen pen = factory1.produce();
        pen.show();
        IPenFactory factory2 = new PenFactory2();
        Pen pen2 = factory2.produce();
        pen.show();
        IPenFactory factory3 = new PenFactory3();
        Pen pen3 = factory3.produce();
        pen.show();
    }
}

抽象产品角色

abstract class Pen {
    abstract void show();
}

具体产品铅笔

class pencil extends Pen {
    @Override
    void show() {
        System.out.println("铅笔");
    }
}

具体产品毛笔

class WritingBrush extends Pen {
    @Override
    void show() {
        System.out.println("毛笔");
    }
}

具体产品圆珠笔

class BallPen extends Pen {
    @Override
    void show() {
        System.out.println("圆珠笔");
    }
}

抽象工厂角色

interface IPenFactory {
    Pen produce();
}

具体工厂1

class PenFactory1 implements IPenFactory {
    @Override
    public Pen produce() {
        return new pencil();
    }
}

具体工厂2

class PenFactory2 implements IPenFactory {
    @Override
    public Pen produce() {
        return new WritingBrush();
    }
}

具体工厂3

class PenFactory3 implements IPenFactory {
    @Override
    public Pen produce() {
        return new BallPen();
    }
}
抽象工厂

抽象工厂跟工厂方法模式一样有4种角色:抽象工厂角色、具体工厂角色、抽象产品角色、具体产品角色,区别在于抽象工厂模式对应的产品是一族相似的,而工厂方法模式只有一个产品。抽象工厂模式实现方式有很多,只需要关注他是否是用来创建多种产品。

public class TestMain {
    public static void main(String[] args) {
        IPenFactory factory1 = new PenFactory1();
        Pen pen = factory1.producePen();
        pen.show();
        IPenFactory factory2 = new PenFactory2();
        Pen pen2 = factory2.producePen();
        pen.show();
    }
}

抽象产品角色

abstract class Pen {
    abstract void show();
}

抽象产品角色

abstract class Notepad {
    abstract void content();
}

抽象产品角色

abstract class Desk {
    abstract void colour();
}

具体产品铅笔

class pencil extends Pen {
    @Override
    void show() {
        System.out.println("铅笔");
    }
}

具体产品毛笔

class WritingBrush extends Pen {
    @Override
    void show() {
        System.out.println("毛笔");
    }
}

具体产品小记事本

class LittleNotepad extends Notepad {
    @Override
    void content() {
        System.out.println("课堂笔记本");
    }
}

具体产品大记事本

class BigNotepad extends Notepad {
    @Override
    void content() {
        System.out.println("产品操作手册");
    }
}

具体产品小办公桌

class LittleDesk extends Desk {
    @Override
    void colour() {
        System.out.println("白色小办公桌");
    }
}

具体产品大办公桌

class BigDesk extends Desk {
    @Override
    void colour() {
        System.out.println("红色大办公桌");
    }
}

工厂

interface IPenFactory {
    Pen producePen();
    Notepad produceNotepad();
    Desk produceDesk();
}

具体工厂

class PenFactory1 implements IPenFactory {
    @Override
    public Pen producePen() {
        return new pencil();
    }
    @Override
    public Notepad produceNotepad() {
        return new LittleNotepad();
    }
    @Override
    public Desk produceDesk() {
        return new LittleDesk();
    }
}

具体工厂

class PenFactory2 implements IPenFactory {
    @Override
    public Pen producePen() {
        return new WritingBrush();
    }
    @Override
    public Notepad produceNotepad() {
        return new BigNotepad();
    }
    @Override
    public Desk produceDesk() {
        return new BigDesk();
    }
}
建造者模式

它可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现的对象。简要的说就是构建过程可以创建不同的对象。
建造模式也有4个角色:导演角色、抽象建造角色、具体建造角色、产品角色。

public class TestMain {
    public static void main(String[] args) {
        Builder builder = new BuilderA();
        Director director = new Director(builder);
        director.produce();
    }
}

具体产品

class Product {
    protected String name;
    protected String colour;
    protected int with;
    protected int length;
}

抽象建造者

abstract class Builder {
    protected Product product=new Product();
    abstract void BuilderName();
    abstract void BuilderColour();
    abstract void BuilderWith();
    abstract void BuilderLength();
    public Product getResult()
    {
        return product;
    }
}

具体建造者

class BuilderA extends Builder {
    @Override
    void BuilderName() {
        product.name = "1";
        product.name += "2";
    }
    @Override
    void BuilderColour() {
        product.colour = "#1";
    }
    @Override
    void BuilderWith() {
        product.with = 10;
    }
    @Override
    void BuilderLength() {
        product.length = 5;
    }
}

导演

class Director {
    Builder builder;
    Director(Builder builder) {
        this.builder = builder;
    }
    Product produce() {
        builder.BuilderName();
        builder.BuilderWith();
        return builder.getResult();
    }
}

抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式不需要关心构建过程,只关心什么产品由什么工厂生产即可。而建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品。
产品之间差异性很大或者产品内部变化很复杂的时候最好不要用建造者模式,只有在内部部件不会变,而其组合经常变化的时候非常适合使用建造者模式

posted @ 2020-04-10 17:29  源码猎人  阅读(294)  评论(0)    收藏  举报