专栏首页Java大联盟23种设计模式详解(二)

23种设计模式详解(二)

1.工厂方法模式(FactoryMethod Pattern)

一、普通工厂方法模式

就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

举例:手机发短信或微信。

手机:

public interface Phone {
    public void send();
}

老年机:

public class oldMachine implements Phone{
    @Override
    public void send() {
        //老年机只能发短信
        System.out.println("发短信");

    }
}

智能机:

public class smartPhone implements Phone {
    @Override
    public void send() {
        //智能机可以发微信
        System.out.println("发微信");
    }
}

工厂:

public class Factory {
    public Phone send(String type){
        if("oldMachine".equals(type)){
            return new oldMachine();
        }else if("smartPhone".equals(type)){
            return new smartPhone();
        }
        return null;
    }
}

测试:

public class Test {
    public static void main(String[] args){
        Factory factory=new Factory();
        Phone phone=factory.send("oldMachine");
        phone.send();
    }
}

结果:

二、多个工厂方法模式

是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

工厂:

public class Factory {
    public Phone sendMail(){
        return new oldMachine();
    }
    public Phone sendWechat(){
        return new smartPhone();
    }
}

测试:

public class Test {
    public static void main(String[] args){
        Factory factory=new Factory();
        Phone phone=factory.sendMail();
        phone.send();
    }
}

结果:

三、静态工厂方法模式

将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

工厂:

public class Factory {
    public static Phone sendMail(){
        return new oldMachine();
    }
    public static Phone sendWechat(){
        return new smartPhone();
    }
}

测试:

public class Test {
    public static void main(String[] args){
        Phone phone=Factory.sendMail();
        phone.send();
    }
}

结果:

2.抽象工厂方法模式(Abstract Factory)

工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。

手机接口:

public interface Phone {
    public void send();
}

老年机:

public class oldMachine implements Phone{
    @Override
    public void send() {
        //老年机只能发短信
        System.out.println("发短信");

    }
}

智能机:

public class smartPhone implements Phone {
    @Override
    public void send() {
        //智能机可以发微信
        System.out.println("发微信");
    }
}

工厂接口:

public interface Send {
    public Phone send();
}

老年机工厂:

public class oldMachineFactory implements Send {
    @Override
    public Phone send() {
        return new oldMachine();
    }
}

智能机工厂:

public class smartPhoneFactory implements Send {
    @Override
    public Phone send() {
        return new smartPhone();
    }
}

测试:

public class Test {
    public static void main(String[] args){
        Send send= new smartPhoneFactory();
        Phone phone=send.send();
        phone.send();
    }
}

结果:

其实这个模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Phone接口,同时做一个工厂类,实现Send接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!

3.门面模式(Facade Pattern)

比如说做饭,你得先买菜,然后洗菜,烹饪,吃;这几个过程顺序不能乱吧,而且缺一不可吧。你想想你上了一天班回来还得这么累,麻烦?麻烦!怎么解决?下馆子呗,告诉厨师你的需求,让他去干,你只需要吃就行。

做饭的过程:

//做饭的过程
public interface Cook {
    //买菜(买哪些菜)
    public void buyVegetables(String vegetables);
    //洗菜
    public void washVegetables();
    //烹饪(什么口味)
    public void cookVegetables(String flavour);
    //吃
    public void eat();
}

做饭的实现类:

//做饭的具体实现
public class cookImpl implements Cook{
    @Override
    public void buyVegetables(String vegetables) {
        System.out.println("买菜。。。。");
    }

    @Override
    public void washVegetables() {
        System.out.println("洗菜。。。。");
    }

    @Override
    public void cookVegetables(String flavour) {
        System.out.println("烹饪。。。。");
    }

    @Override
    public void eat() {
        System.out.println("吃。。。。");
    }
}

餐馆:

public class Restaurant {
    private Cook cook=new cookImpl();
    public void cook(String vegetables,String flavour){
        cook.buyVegetables(vegetables);
        cook.washVegetables();
        cook.cookVegetables(flavour);
        cook.eat();
    }
}

你去下馆子:

public class Client {
    public  static void main(String[] args){
        Restaurant rs=new Restaurant();
        //想吃鱼
        String vegetables="fish";
        //酸辣味
        String flavour="sour and hot";
        rs.cook(vegetables,flavour);
    }
}

结果:

如果厨师做饭的过程中,卫生局来检查了,刚好抽中了你这盘菜呢?

卫生局:

public class healthDepartment {
    public void check(Cook cook){};
}

修改餐厅类:

public class Restaurant {
    private Cook cook=new cookImpl();
    private healthDepartment hd=new healthDepartment();
    public void cook(String vegetables,String flavour){
        cook.buyVegetables(vegetables);
        cook.washVegetables();
        cook.cookVegetables(flavour);
        hd.check(cook);
        cook.eat();
    }
}

结果:

食材健康?健康,但是你看不到检查这个过程。

什么时候用呢?开发过程中,遇到水平比较渣的程序员,尽量安排他负责独立模块,然后封装成一个门面模式,让其他团队成员不至于看到这些烂代码糟心。

4.适配器模式(Adapter Pattern)

适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

类的适配器模式:

Source类:

public class Source {
    public void method1(){
        System.out.println("Source的method方法");
    }
}

Target接口:

public interface Target {
    //source类的方法
    public void method1();
    //新的方法
    public void method2();
}

适配器:

public class Adapter extends Source implements Target {
    @Override
    public void method2() {
        System.out.println("Target的method方法");
    }
}

测试:

public class Test {
    public static void main(String[] args){
        Target target=new Adapter();
        target.method1();
        target.method2();
    }
}

结果:

这样Target接口的实现类就具有了Source类的功能。

对象的适配器模式:

基本思路和类的适配器模式相同,只是将Adapter类作修改,这次不继承Source类,而是持有Source类的实例,以达到解决兼容性的问题。

修改Adapter类:

public class Adapter implements Target {
    private Source source;

    public Adapter(Source source) {
        this.source = source;
    }

    @Override
    public void method1() {

    }

    @Override
    public void method2() {
        System.out.println("Target的method方法");
    }
}

测试:

public class Test {
    public static void main(String[] args){
        Source source=new Source();
        Target target=new Adapter(source);
        target.method1();
        target.method2();
    }
}

结果:

接口的适配器模式:

有时我们一个接口中有多个抽象方法,当我们写该接口的实现类时,必须实现该接口的所有方法,这明显有时比较浪费,因为并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,所以我们写一个类,继承该抽象类,重写我们需要的方法就行。

接口:

public interface Target {
    //source类的方法
    public void method1();
    //新的方法
    public void method2();
}

抽象类:

public abstract class Wraaper implements Target {
    @Override
    public void method1() {

    }

    @Override
    public void method2() {

    }
}

S1:

public class S1 extends Wraaper {
    @Override
    public void method1() {
        System.out.println("S1");
    }
}

S2:

public class S2 extends Wraaper {
    @Override
    public void method2() {
        System.out.println("S2");
    }
}

测试:

public class Test {
    public static void main(String[] args){
        S1 ss=new S1();
        S2 sm=new S2();
        ss.method1();
        ss.method2();
        sm.method1();
        sm.method2();
    }
}

结果:

源码:

链接:https://pan.baidu.com/s/1nZGYaUbcri9hI4uqNLHN1Q

密码:i1cm

本文分享自微信公众号 - Java大联盟(javaunion)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-05-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 23种设计模式详解(二)

    是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

    南风
  • 23种设计模式详解(三)

    南风
  • 23种设计模式详解(六)

    南风
  • 23种设计模式详解(二)

    是对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

    南风
  • 在C#中使用依赖注入-工厂模式和工厂方法模式

    工厂模式和工厂方法模式是设计模式中较为常见的两种模式,借助于依赖注入可以更好的发挥模式的特性。本文将通过一个业务需求的变化过程来阐述如何更好的使用设计模式与依赖...

    newbe36524
  • .NET基础拾遗(2)面向对象的实现和异常的处理基础

      在C#中申明一个类型时,只支持单继承(即继承一个父类),但支持实现多个接口(Java也是如此)。像C++可能会支持同时继承自多个父类,但.NET的设计小组认...

    Edison Zhou
  • Spring Boot 2.X(十八):集成 Spring Security-登录认证和权限控制

    在企业项目开发中,对系统的安全和权限控制往往是必需的,常见的安全框架有 Spring Security、Apache Shiro 等。本文主要简单介绍一下 Sp...

    朝雾轻寒
  • 设计模式学习 - 工厂模式

    根据不同的对象,提供不同的工厂,然后由客户端来选择对应的工厂。这也是与简单工厂模式的不同的地方。

    许杨淼淼
  • ASP.NET Web API中的依赖注入什么是依赖注入ASP.NET Web API依赖解析器使用Unity解析依赖配置依赖解析

    什么是依赖注入     依赖,就是一个对象需要的另一个对象,比如说,这是我们通常定义的一个用来处理数据访问的存储,让我们用一个例子来解释,首先,定义一个领域模型...

    小白哥哥
  • JAVA初中级程序员笔试试题

    (多选题) 1.以下哪些不是Java保留字__________ A. private     B. Final    C. class    D. Thro...

    用户2192970

扫码关注云+社区

领取腾讯云代金券