美文网首页
对于JAVA设计模式的自我修养

对于JAVA设计模式的自我修养

作者: 小明同学机器人 | 来源:发表于2021-05-29 18:28 被阅读0次

对于JAVA设计模式的自我修养

一 、工厂模式

这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。

1. 抽象工厂模式

抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

抽象工厂模式中,此例为A和B两家工厂,都生产小汽车和船,需要哪个工厂的船或者车子,在AFactoryThing 或者BFactoryThing中生产所需要的东西即可

类图

image-20210527103006439.png

案例设计思路

  1. 创建一个工厂接口包含A和B工厂生产的方法,返回值为A中产品的父类,即满足无需指定它们具体的类。
  2. 创建A、B工厂并实现1中的接口 ,A中生产A产品,若A生产B则非法权限,B反之
  3. 创建A、B两工厂的自营店,分别继承AB工厂,实现AB工厂的规章制度,变量和方法
  4. 最后将写入自己工厂的产品类,继承自己的自营店。

代码案例

public interface AbstractCreateFactory {
    AFactoryThing createAFactoryThing(int id);
    BFactoryThing createBFactoryThing(int id);

}
public class AFactoryThing  extends ProduceAFactory{
    public int price = 0;
    public String name = "A";

    public void toProduce() {
        System.out.println("这是我们A公司的" + name + "\t价格为" + price);
    }
//从超市买东西,超市自己从商店买东西
}
public  class BFactoryThing extends  ProduceBFactory {
    public int price = 0;
    public String name = "B";

    public void toProduce() {
        System.out.println("这是我们B公司的" + name + "\t价格为" + price);
    }
    
}
public class CarA extends AFactoryThing {
    public CarA() {
        price=9;
        name="车子";
        toProduce();
    }
}
public class CarB extends BFactoryThing {
    public CarB() {
        name = "车子";
        price = 10;
        toProduce();
    }
}

public class ProduceAFactory implements AbstractCreateFactory {
    @Override
    public AFactoryThing createAFactoryThing(int id) {
        AFactoryThing aFactoryThing = null;
        switch (id) {
            case 0:
                aFactoryThing = new CarA();
                break;
            case 1:
                aFactoryThing = new ShipA();

                break;
            default:
                aFactoryThing = new CarA();
                break;
        }

        return aFactoryThing;
    }

    @Override
    public BFactoryThing createBFactoryThing(int id) {
        System.out.println("A工厂没有权限生产B产品");
        return null;

    }
}
public class ProduceBFactory implements AbstractCreateFactory {
    @Override
    public AFactoryThing createAFactoryThing(int id) {
        System.out.println("B工厂没有权限生产A产品");
       return  null;
    }

    @Override
    public BFactoryThing createBFactoryThing(int id) {
        BFactoryThing bFactoryThing=null;

        switch (id) {
            case 0:
                bFactoryThing=new CarB();
                break;
            case 1:
                bFactoryThing=new ShipB();
                break;
            default:
                bFactoryThing=new CarB();

                break;
        }
        return bFactoryThing;
    }
}
public class ShipA extends AFactoryThing {


    public ShipA() {
        price = 19;
        name = "船";
        toProduce();
    }

}
public class ShipB extends BFactoryThing {

    public ShipB() {
        price = 20;
        name = "船";
        toProduce();
    }
}
public class Client {
    public static void main(String[] args) {
        AFactoryThing aFactoryThing = new AFactoryThing();
        BFactoryThing bFactoryThing = new BFactoryThing();
        aFactoryThing.createAFactoryThing(0);
        aFactoryThing.createAFactoryThing(1);
        bFactoryThing.createBFactoryThing(0);
        ShipB bFactoryThing1 = (ShipB)bFactoryThing.createBFactoryThing(1);
    }
}


2. 简单工厂模式

类图

image-20210527103111402.png
  • 我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。

案例设计思路

简单工厂模式的创作思路就更简单了,工厂接口类,本例中用到了操作类工厂,返回自己需要的类型即可

代码案例

public interface AbstractCalculateFactory {
    OperationCal createOperationCal(String message);
}
public class AddCalculate extends OperationCal {
    public  AddCalculate() {
        message=add;
        result = x + y;
        showResult();
    }
}
public class DivCalculate extends OperationCal {
    public DivCalculate() {
        message = div;
        result = x / y;
        showResult();
    }
}
public class MulCalculate extends  OperationCal{
    public  MulCalculate() {
        message=mul;
        result = x * y;
      showResult();
    }
}
public class ReduceCalculate extends OperationCal {
    public ReduceCalculate() {
        message = red;
        result = x - y;
        showResult();
    }
}
public class OperationCal implements AbstractCalculateFactory {
    public double x = 16;
    public double y = 8;
    public double result = 0;
    public String message = "";
    public static String add="ADD";
    public static String red="RED";
    public static String mul="MUL";
    public static String div="DIV";
    @Override
    public OperationCal createOperationCal(String message) {

        OperationCal operationCal = null;
        switch (message) {
            case "add":
                operationCal = new AddCalculate();
                break;
            case "red":
                operationCal = new ReduceCalculate();
                break;
            case "mul":
                operationCal = new MulCalculate();
                break;
            case "div":
                operationCal = new DivCalculate();
                break;
            default:
                operationCal = new DivCalculate();
                System.out.println("操作有误");
        }

        return operationCal;
    }

    public void showResult() {
        System.out.println(x + message + y + "的结果为" + result + "\n");
    }
}

public class OperationClient {
    public static void main(String[] args) {
      OperationCal operationCal=new OperationCal();
      operationCal.createOperationCal("div");
      operationCal.createOperationCal("mul");
      operationCal.createOperationCal("add");
      operationCal.createOperationCal("red");

    }
}

二、建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

类图

image-20210527103217571.png

抽象类实现接口后 不用实现接口的所有方法 ,非抽象类就得实现接口的所有方法

普通类继承抽象类后,得重写实现抽象类未实现的方法!

案例设计思路

  1. 本实例中创建了Item(商品类目)和Packing(打包) 的接口,Item描述了name,packing和price方法,Packing描述了pack方法

  2. 实现接口 注意 Item(商品类目)包含Burger(汉堡)和ColdDrink(冷饮)两个抽象类 (注意为何写抽象类,抽象类中的price()方法可以忽略,那是一个抽象方法,不是实现Item中的price方法)所以抽象类只实现了packing方法,剩下两个方法在子类中实现的.(层层搭建)

  3. 瓶装和袋装两个类实现Packing接口,实体类封装搭建完毕之后开始管理类的搭建

  4. 做菜单管理类 meal ,添加商品(添加商品直接为item对象,不管是点什么菜品都加入其中即可),计算价钱,返回商品

  5. 最后MealBuilder 菜单建造者类 相当于客人点菜类,点好菜后,Meal 返回。

代码案例

package com.example.xm.build;

import java.util.ArrayList;
import java.util.List;

public interface Item {
    public String name();
    public Packing packing();
    public float price();
}
interface Packing {
    public String pack();
}
 class Wrapper implements Packing {

    @Override
    public String pack() {
        return "Wrapper";
    }
}
 class Bottle implements Packing {

    @Override
    public String pack() {
        return "Bottle";
    }
}
abstract class Burger implements Item {

    @Override
    public Packing packing() {
        return new Wrapper();
    }


    @Override
    public abstract float price();
}
abstract class ColdDrink implements Item {

    @Override
    public Packing packing() {
        return new Bottle();
    }

    @Override
    public abstract float price();
}
class VegBurger extends Burger {
    @Override
    public String name() {
        return "Veg Burger";
    }

    @Override
    public float price() {
        return 0;
    }
}
class ChickenBurger extends Burger {

    @Override
    public float price() {
        return 50.5f;
    }

    @Override
    public String name() {
        return "Chicken Burger";
    }
}
class Coke extends ColdDrink {

    @Override
    public float price() {
        return 30.0f;
    }

    @Override
    public String name() {
        return "Coke";
    }
}
class Pepsi extends ColdDrink {

    @Override
    public float price() {
        return 35.0f;
    }

    @Override
    public String name() {
        return "Pepsi";
    }
}
class Meal {
    private List<Item> items = new ArrayList<Item>();

    public void addItem(Item item){
        items.add(item);
    }

    public float getCost(){
        float cost = 0.0f;
        for (Item item : items) {
            cost += item.price();
        }
        return cost;
    }

    public void showItems(){
        for (Item item : items) {
            System.out.print("Item : "+item.name());
            System.out.print(", Packing : "+item.packing().pack());
            System.out.println(", Price : "+item.price());
        }
    }
}
class MealBuilder {
    public Meal prepareVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Coke());
        return meal;
    }

    public Meal prepareNonVegMeal (){
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new Pepsi());
        return meal;
    }
}
class BuilderPatternDemo {
    public static void main(String[] args) {
        MealBuilder mealBuilder = new MealBuilder();

        Meal vegMeal = mealBuilder.prepareVegMeal();
        System.out.println("Veg Meal");
        vegMeal.showItems();
        System.out.println("Total Cost: " +vegMeal.getCost());

        Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
        System.out.println("\n\nNon-Veg Meal");
        nonVegMeal.showItems();
        System.out.println("Total Cost: " +nonVegMeal.getCost());
    }
}

三、原型模式

原型模式是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。(通过克隆返回对象)

这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。(缓存对象,克隆返回对象)

类图

image-20210527103238348.png

原型模式中设计思路 加载缓存返回缓存对象

案例设计思路

  1. 代码以加载图形和缓存为案例,创建三种图形类(相当于数据库的操作)
  2. 然后将图形加入到缓存中,ShapeCache 中的loadCache方法
  3. 其次再用getShape(id) 返回所需要的图形对象

原型模式的优点就是高性能,需要某个对象的时候能够快速的构建出来

另外 原型模式可逃避构造函数的约束。不需要new 的方式构建新对象

代码案例

public abstract class Shape implements Cloneable {
    private String id;
    protected  String type="默认";
    abstract void draw();
    public String getType() {
        return type;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getId() {
        return id;
    }
    @Override
    protected Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    } 
}

public class Circle extends Shape {

    public Circle() {
        type = "圆";
    }
    @Override
    void draw() {
        System.out.println("画了一个" + type);
    }
}

public class Rectangle extends Shape {
    public Rectangle() {
        type = "Rectangle";
    }
    @Override
    void draw() {
        System.out.println("画了一个"+type);
    }
}

public class Square extends Shape {
    public Square() {
        type = "Square";
    }
    @Override
    void draw() {
        System.out.println("画了一个"+type);
    }
}

public class ShapeCache { //形状缓存区
    private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>();

    //读取形状
     public static Shape getShape(String shapeId) {
        Shape cache = shapeMap.get(shapeId);
        return (Shape) cache.clone();

    }
     public static void loadCache() {
        Circle circle = new Circle();
        circle.setId("1");

        Square square = new Square();
        square.setId("2");

        Rectangle rectangle = new Rectangle();
        rectangle.setId("3");
        shapeMap.put(circle.getId(), circle);
        shapeMap.put(square.getId(), square);
        shapeMap.put(rectangle.getId(), rectangle);
    }
}

public class PrototypeClient {
    public static void main(String[] args) {
        ShapeCache.loadCache(); //加载缓存
        Shape shape = ShapeCache.getShape("1");
      shape.draw();
        Shape shape1 = ShapeCache.getShape("2");
        shape1.draw();
        Shape shape2 = ShapeCache.getShape("3");
        shape2.draw();
    }
}

四、适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。

这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。

适配器是什么,先从宏观上生活上,它就是一个用来适配某个东西来达到某种效果的一个物体,起到一个转换作用或者是红线作用

例子:本例子遵循菜鸟教程例子:有一个音频播放器,但是只支持mp3格式的播放,然后做了一个适配器,将音频播放器和适配器连接,播放mp4和vlc的音频,所以再音频播放器里直接调用适配器即可

类图

image-20210527113237917.png

案例设计思路

  1. 适配器模式的代码对菜鸟做了略微的修改,修改后相对于原先更美观,更简洁
  2. 首先建立一个接口AdvanceMediaPlayer ,用mp4和vlc 两个类实现
  3. 然后建立一个适配器MediaAdapter,实现播放mp4和vlc为文件
  4. 最后将原始播放器拿过来继承适配器,这样原来的播放器就会支持本来的mp3和现有的mp4,vlc文件
  5. 最后Client 将需要的文件播放

代码案例


public interface AdvanceMediaPlayer {
    void playVlc(String fileName);
    void playMp4(String fileName);
}

public interface MediaPlayer {
    void play(String audioTYpe,String fileName);
}

public class Mp4Player implements AdvanceMediaPlayer {

    @Override
    public void playVlc(String fileName) {
        System.out.println("文件不匹配");
    }

    @Override
    public void playMp4(String fileName) {
        System.out.println("播放了Mp4" + fileName);

    }
}

public class VlcPlayer implements AdvanceMediaPlayer {
    @Override
    public void playVlc(String fileName) {
        System.out.println("播放了VLC"+fileName);
    }

    @Override
    public void playMp4(String fileName) {
        System.out.println("文件不匹配");
    }
}

public class MediaAdapter implements MediaPlayer {
    private AdvanceMediaPlayer advanceMediaPlayer;

    public void prepareAudio(String audioType) {

        if (audioType.equalsIgnoreCase("vlc")) {
            advanceMediaPlayer = new VlcPlayer();
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advanceMediaPlayer = new Mp4Player();
        }

    }


    @Override
    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("vlc")) {
            advanceMediaPlayer.playVlc(fileName);
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advanceMediaPlayer.playMp4(fileName);
        }
    }
}

public class AudioPlay extends MediaAdapter{

    public AudioPlay() {
    }

    @Override
    public void play(String audioTYpe, String fileName) {
        if (audioTYpe.equalsIgnoreCase("vlc") || audioTYpe.equalsIgnoreCase("mp4")) {
            super.prepareAudio(audioTYpe);
            super.play(audioTYpe, fileName);
        } else if (audioTYpe.equalsIgnoreCase("mp3")) {
            System.out.println("播放mp3");
        } else {
            System.out.println("不支持该文件");
        }
    }
}

public class AdapterClient {
    public static void main(String[] args) {
        AudioPlay audioPlayer = new AudioPlay();
        audioPlayer.play("vlc","java.vlc");
        audioPlayer.play("mp4","java.mp4");
        audioPlayer.play("mp3","java.mp3");
        audioPlayer.play("m","java.m");
    }
}

五、桥接模式

桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。

类图

image-20210529124751423.png

案例设计思路

  1. 桥接模式抽象类调用接口,实现代码独立通过抽象类来聚合接口,调用抽象类的子类,完成程序
  2. 定义好DrawApi 接口类,并用绿圆和红圆实现接口
  3. 再定义图形Shape类,聚合接口类,构造传参数,并抽象一个draw的方法
  4. 最后定义Circle类,继承Shape,实现draw方法,该方法里聚合接口类的方法,完成桥接模式。

代码案例

interface  DrawApi {
    void drawCircle();
}

public class RedCircle  implements  DrawApi{
    @Override
    public void drawCircle() {
        System.out.println("画了一个红色的圆");
    }
}

public class GreenCircle  implements  DrawApi{
    @Override
    public void drawCircle() {
        System.out.println("画了一个绿色的圆");

    }
}

public abstract class Shape {
    public DrawApi drawApi;

    public Shape(DrawApi drawApi) {
        this.drawApi = drawApi;
    }
    abstract void draw();
}

public class Circle extends Shape {
    public Circle(DrawApi drawApi) {
        super(drawApi);
    }

    @Override
    void draw() {
       drawApi.drawCircle();
    }
}

public class BridgeClient {
    public static void main(String[] args) {
        RedCircle redCircle = new RedCircle();
        GreenCircle greenCircle = new GreenCircle();
        Shape circle = new Circle(redCircle);
        Shape circle1 = new Circle(greenCircle);
        circle.draw();
        circle1.draw();
    }
}

六、单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。1.

懒汉式,线程不安全

public class LazySingle {
    private static LazySingle lazySingle;
//调用实例方法时候再判断是否存在实例对象,线程不安全,操作不规范可能创建多个对象
    public static LazySingle getInstance() {
        if (lazySingle == null) {
            lazySingle = new LazySingle();
        }
        return lazySingle;
    }
}

懒汉式,线程安全

public class LazySingleSafe {
    private static LazySingleSafe lazySingleSafe;

    public static synchronized LazySingleSafe getInstance() {
//调用实例方法时候再判断是否存在实例对象,只不过方法加了个线程锁,防止多个线程同时进入
        if (lazySingleSafe == null) {
            lazySingleSafe = new LazySingleSafe();
        }
        return lazySingleSafe;
    }
}

饿汉式

public class HungrySingle {
    private static HungrySingle hungrySingle = new HungrySingle();
//先加载创建好对象后,调用实例方法直接返回静态对象
    public static HungrySingle getInstance() {
        return hungrySingle;
    }

}

双检锁/双重校验锁

public class DoubleCheckSingle {
    private static DoubleCheckSingle doubleCheckSingle;
//内部类 利用类加载器机制,进行同步锁,指挥加载一次,不会同时进入线程锁里面
    public DoubleCheckSingle getInstances() {
        if (doubleCheckSingle == null) {
            synchronized (DoubleCheckSingle.class) {
                if (doubleCheckSingle == null) {
                    doubleCheckSingle = new DoubleCheckSingle();
                }
                
            }

        }
        return doubleCheckSingle;
    }

}

登记式/静态内部类

//内部类方式的单例模式
public class StaticSingle {
    private static class StaticSingleHolder {
        private static StaticSingle single = new StaticSingle();
    }
//这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,
// 应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,
// 双检锁方式可在实例域需要延迟初始化时使用。
    public StaticSingle getInstance() {

        return StaticSingleHolder.single;
    }
}

枚举

public enum EchoSingle {
    INSTANCE;
}
//枚举机制的单例
class Client {
    public static void main(String[] args) {
        EchoSingle echoSingle = EchoSingle.INSTANCE;

    }
}

相关文章

  • 对于JAVA设计模式的自我修养

    对于JAVA设计模式的自我修养 一 、工厂模式 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。...

  • 设计模式

    Java 设计模式情景分析 ——单例模式 Java 设计模式情景分析——建造者模式 Java 设计模式情景分析——...

  • Java 设计模式《概述》设计模式,如此简单~

    博客专栏 Java设计模式系列内容,就现在,让设计模式如此简单。 Java设计模式系列文章 Java 设计模式(一...

  • Java设计模式教程

    Java设计模式教程 Java工厂设计模式 Java抽象工厂模式 Java单例模式 Java建造者(Builder...

  • Android中涉及的模式

    我的Java设计模式-建造者模式 我的Java设计模式-观察者模式 重学设计模式之单例模式

  • 了解外观模式

    java 设计模式 ------外观模式 Java中一共有23种设计模式,每种设计模式各有特...

  • JAVA模板方法设计模式——Java设计模式,写漂亮的代码——

    Java设计模式,写漂亮的代码 ————模板方法设计模式 简介: 模板方法设计模式是Java设计模式中很简单、应用...

  • 工厂模式

    java设计模式-工厂模式 工厂模式: 工厂模式是java设计模式里最常用的设计模式之一。 工厂模式属于创建型模式...

  • 装饰者模式——IO流运用

    推荐博客Java设计模式学习09Java设计模式学习09Java设计模式学习09 装饰者模式还是比较难懂的。。。。...

  • Design Patterns

    设计模式 ref:设计模式Java版Java开发中的23种设计模式详解 Source Code: https://...

网友评论

      本文标题:对于JAVA设计模式的自我修养

      本文链接:https://www.haomeiwen.com/subject/ixuklltx.html