Java实现23种设计模式教程(作者原创)

举报
摸鱼打酱油 发表于 2022/04/01 22:38:35 2022/04/01
【摘要】 简单工厂模式(推荐使用)总结:主要依靠if elseif 在一个大的工厂类中根据不同的传参来new不同的对象,这个大的工厂必须要是一个品类,比如手机工厂和电脑工厂要分开,后面的抽象工厂模式才能通过一个品牌分类,这里简单工厂和工厂方法只能一个种类的工厂(但是可以写多个工厂类)实体类要提供一个类型的接口,工厂模式返回对象需要多态,所以要有接口或者父类public interface phone...

简单工厂模式(推荐使用)

总结:主要依靠if elseif 在一个大的工厂类中根据不同的传参来new不同的对象,这个大的工厂必须要是一个品类,比如手机工厂和电脑工厂要分开,后面的抽象工厂模式才能通过一个品牌分类,这里简单工厂和工厂方法只能一个种类的工厂(但是可以写多个工厂类)

实体类要提供一个类型的接口,工厂模式返回对象需要多态,所以要有接口或者父类

public interface phone {
    //使用接口来实现多态写法

    String getPhoneName();

}
public class iphone implements phone {

    /**
     * 苹果手机
     */
    private String id;
    private String name;
    private double price;

    public iphone() {
    }

    public iphone(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public void setId(String id) {
        this.id = id;
    }

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

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "iphone{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    @Override
    public String getPhoneName() {
        return this.name;
    }
}


public class xiaomiPhone implements phone {

    /**
     * 小米手机
     */
    private String id;
    private String name;
    private double price;

    public xiaomiPhone() {
    }

    public xiaomiPhone(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public void setId(String id) {
        this.id = id;
    }

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

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "xiaomiPhone{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

    @Override
    public String getPhoneName() {
        return this.name;
    }
}

简单工厂(核心代码实现)

public class phoneFactory {

    /**
     * 简单工厂模式
     * 缺点:不满足设计模式原则-开闭原则(对扩展性开,对修改关闭)
     */

    //简单工厂根据传参去判断new哪个对象,因为这里要使用多态写法,所以下面要定义一个接口,哪怕空接口都行,extends也行
    public static phone getPhone(String name){

        if(name==null||name.equals(""))
            return null;
        if(name.equals("小米"))
            return new xiaomiPhone("mi-001","小米11",4999.0);
        else if(name.equals("苹果"))
            return new iphone("iphone-888","iPhone12 Pro max",10999.0);
        return null;
    }




}

测试

class phoneFactoryMain{

    public static void main(String[] args) {
        //通过工厂就可以获得对象
        phone p1 = phoneFactory.getPhone("");
        phone p2 = phoneFactory.getPhone("小米");
        phone p3 = phoneFactory.getPhone("苹果");
        System.out.println(p1);
        System.out.println(p2.getPhoneName());
        System.out.println(p3.getPhoneName());
    }

}
null
小米11
iPhone12 Pro max

简单工厂模式弊端

试想,当我们需要添加一款手机的时候,我们需要在工厂类的if else 里面添加new新手机的代码,这样就违反了设计模式的开闭原则了,这时候我们如果很介意这个开闭原则的话,可以使用工厂方法模式

工厂方法模式(拆分简单工厂)

总结:工厂方法也就是为了解决简单工厂不满足设计模式原则中的开闭原则,工厂方法不采用简单工厂那种在一个大工厂(单一类型,比如手机工厂、电脑工厂要分开不同的工厂)中通过if elseif 根据不同的传参来new不同的对象了,而是把这个大的工厂拆分。拆分成一个工厂接口,

简单工厂是一个大的综合一个类型的工厂,而工厂方法模式是各自品牌类型的东西单独建立一个工厂,这样更符合我们日常生活的情况,比如手机里面有小米手机、苹果手机,这样工厂又会拆分成小米手机工厂、苹果手机工厂

public abstract class factory {

    /**
     * 这个工厂是生产手机,所以我们要提供一个抽象方法来生产手机
     */

    //抽象类的获取手机方法,一定不能指定获取什么手机,要用多态。
    abstract phone getPhoneByFactory();



}

苹果手机工厂

public class iPhoneFactory extends factory {

    /**
     * 苹果手机工厂
     */


    @Override
    phone getPhoneByFactory() {
        return new iphone("iphone-888","iPhone12 Pro max",10999.0);
    }



}

小米手机工厂

public class xiaomiFactory extends factory{

    /**
     * 小米手机工厂
     */
    @Override
    phone getPhoneByFactory() {
        return new xiaomiPhone("mi-001","小米11",4999.0);
    }
}

苹果手机实体类

public class iphone implements phone {

    /**
     * 苹果手机
     */
    private String id;
    private String name;
    private double price;

    public iphone() {
    }

    public iphone(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public void setId(String id) {
        this.id = id;
    }

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

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "iphone{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}

小米手机实体类

public class xiaomiPhone implements phone{

    //小米手机
    private String id;
    private String name;
    private double price;

    public xiaomiPhone() {
    }

    public xiaomiPhone(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public void setId(String id) {
        this.id = id;
    }

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

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "xiaomiPhone{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", price=" + price +
                '}';
    }

}

手机接口:

public interface phone {
}

利用各自的手机工厂创建手机对象

public class factoryMethodMain {

    public static void main(String[] args) {

        factory xiaomiFactory = new xiaomiFactory();
        factory iPhoneFactory = new iPhoneFactory();

        System.out.println(xiaomiFactory.getPhoneByFactory());
        System.out.println(iPhoneFactory.getPhoneByFactory());


    }

}

抽象工厂模式(很大的工厂)

总结:抽象工厂模式是生产一个品牌的任何产品(比如某一个抽象工厂,小米工厂去实现它,那么小米工厂就是抽象工厂的子类,也就是说小米工厂可以小米品牌下的所有商品,也就是说这个小米工厂可以生产小米手机、小米笔记本、小米电脑、小米耳机等等。。。),而工厂模式不可以,工厂模式只能生产同一类产品,比如就生产笔记本,但是。如果抽象工厂定义的生产产品只有一类品牌产品,那么这个抽象工厂模式就和工厂模式没有区别了。(当且仅当抽象工厂只有一个抽象方法时)

需求:小米公司和华为公司要生产手机和电脑。

定义抽象工厂:

public abstract class abstractFactory {

    /**
     * 抽象工厂模式的抽象工厂:生产手机和电脑
     * 如果是工厂方法模式的抽象工厂:只能生产手机或者只生产电脑
     */

    public abstract phone getPhone();  //生产手机


    public abstract computer getComputer();  //生产电脑



}

定义华为品牌的工厂(生产多个类型产品)

public class huaweiFactory extends abstractFactory {


    @Override
    public phone getPhone() {
        return new huaweiPhone("h-05","华为Mate40 pro",5388.0);
    }

    @Override
    public computer getComputer() {
        return new huaweiComputer("h-33","华为笔记本电脑",5800.0);
    }


}

定义小米品牌的工厂(生产多个类型产品)

public class xiaomiFactory extends abstractFactory {


    @Override
    public phone getPhone() {
        return new xiaomiPhone("x-01","小米11",3999.0);
    }

    @Override
    public computer getComputer() {
        return new xiaomiComputer("x-22","小米笔记本电脑",5213.0);
    }


}

手机接口:

public interface phone {


}

电脑接口:

public interface computer {
    
}

实体类:

public class xiaomiPhone implements phone {

    /**
     * 小米手机
     */
    private String id;
    private String name;
    private double price;

    public xiaomiPhone() {
    }

    public xiaomiPhone(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }
public class huaweiComputer implements computer {

    private String id;
    private String name;
    private double price;


    public huaweiComputer() {
    }

    public huaweiComputer(String id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

测试类:

public class abstractFactoryMain {

    /**
     * 抽象工厂模式
     */

    public static void main(String[] args) {

        //创建小米的大工厂
        xiaomiFactory xiaomiFactory = new xiaomiFactory();
        //创建华为的大工厂
        huaweiFactory huaweiFactory = new huaweiFactory();
        //从小米的大工厂中生产小米手机和小米笔记本
        phone xiaomiPhone = xiaomiFactory.getPhone();
        computer xiaomComputer = xiaomiFactory.getComputer();
        System.out.println(xiaomiPhone);
        System.out.println(xiaomComputer);
        //从华为的大工厂中生产华为手机和华为笔记本
        System.out.println("=======================");
        phone huaweiPhone = huaweiFactory.getPhone();
        computer huaweiComputer = huaweiFactory.getComputer();
        System.out.println(huaweiPhone);
        System.out.println(huaweiComputer);


    }


}

建造者模式

用于创建复杂对象,比如构造方法多变的情况下使用建造者模式很好用

建造者所需角色:抽象建造者、具体建造者、指挥者(非必要,可有可无:用于拼装建造的顺序)、测试

比如有一个项目:我们要建造一台电脑,里面有cpu、显卡、内存条、键盘等等。。(使用建造者模式实现这个项目)

抽象建造者:

public abstract class builder {

    //抽象建造者提供建造对象所需要的方法

    /*
    实现链式编程,addCPU等方法要返回一个builder对象
     */
    public abstract builder addCPU(String cpu); //添加CPU

    public abstract builder addXianka(String xianka); //添加显卡

    public abstract builder addShubiao(String shubiao); //添加鼠标

    public abstract builder addKeyboard(String keyboard);//添加键盘

    public abstract builder addMemory(String memory); //添加内存条

    public abstract computer builderComputer(); //返回构建的computer对象

}

具体建造者:

public class computerBuilder extends builder {

    private computer computer=new computer();

    //给电脑默认属性
    public computerBuilder(){
        computer.setCpu("i3");
        computer.setKeyboard("联想键盘");
        computer.setMemory("金士顿8g内存");
        computer.setShubiao("华硕鼠标");
        computer.setXianka("GTX1060");
    }


    @Override
    public builder addCPU(String cpu) {
        computer.setCpu(cpu);
        return this; //返回当前调用者的对象,实现链式编程
    }

    @Override
    public builder addXianka(String xianka) {
        computer.setXianka(xianka);
        return this;
    }

    @Override
    public builder addShubiao(String shubiao) {
        computer.setShubiao(shubiao);
        return this;
    }

    @Override
    public builder addKeyboard(String keyboard) {
        computer.setKeyboard(keyboard);
        return this;
    }

    @Override
    public builder addMemory(String memory) {
        computer.setMemory(memory);
        return this;
    }

    @Override
    public computer builderComputer() {
        return computer;
    }


}

public class computer {
    private String cpu;
    private String xianka;
    private String shubiao;
    private String keyboard;
    private String memory; //内存

    public computer() {
    }

    public computer(String cpu, String xianka, String shubiao, String keyboard, String memory) {
        this.cpu = cpu;
        this.xianka = xianka;
        this.shubiao = shubiao;
        this.keyboard = keyboard;
        this.memory = memory;
    }

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getXianka() {
        return xianka;
    }

    public void setXianka(String xianka) {
        this.xianka = xianka;
    }

    public String getShubiao() {
        return shubiao;
    }

    public void setShubiao(String shubiao) {
        this.shubiao = shubiao;
    }

    public String getKeyboard() {
        return keyboard;
    }

    public void setKeyboard(String keyboard) {
        this.keyboard = keyboard;
    }

    public String getMemory() {
        return memory;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    @Override
    public String toString() {
        return "computer{" +
                "cpu='" + cpu + '\'' +
                ", xianka='" + xianka + '\'' +
                ", shubiao='" + shubiao + '\'' +
                ", keyboard='" + keyboard + '\'' +
                ", memory='" + memory + '\'' +
                '}';
    }
}

director(可写可不写):也可以直接操作具体建造者,下面会有用director和不用director的写法:

public class director {
    /**
     * 指挥者。用来拼装具体建造者实现的方法
     */

    private builder builder;

//    私有化构造器,也可以不这么写
    private director(){

    }

    public director(builder builder){
        this.builder=builder;
    }



    //拼装方法
    public computer builder(){

        builder.addCPU("director_cpu");
        builder.addXianka("director_xianka");

        return builder.builderComputer();
    }




}

Main测试:

public class builderMain {


    public static void main(String[] args) {

        System.out.println("不采用director类"); //不采用director类
        builder builder=new computerBuilder();

        computer computer = builder.builderComputer();
        System.out.println(computer);

        computer computer1 = builder.addCPU("i5").addXianka("RTX2080").builderComputer();
        System.out.println(computer1);

        computer computer2 = builder.addCPU("i7").addXianka("RTX2090").addMemory("金士顿32g").addShubiao("华为鼠标").builderComputer();
        System.out.println(computer2);

        System.out.println("=============");
        System.out.println("采用director类"); //采用director类
        director director = new director(new computerBuilder());
        computer builder1 = director.builder();
        System.out.println(builder1);



    }

}

代理模式

静态代理

被代理的类

public class logger implements Mylogger {

    /**
     * 静态代理:
     *  当我们有个接口的实现类,其中需要对实现类的方法进行增强而不修改源代码,我们可以用代理模式
     *  需求:我们想不改变源代码的情况下对下面 System.out.println("写入日志。");的前面和后面加入一个输出语句
     *
     *  实现:我们只需要创建一个logger的代理类,并实现Mylogger接口,重写方法即可
     */
    @Override
    public void writerLog() {

        System.out.println("写入日志。");

    }



}

接口:

public interface Mylogger {

    public void writerLog();

}

代理类:

public class proxyLogger implements Mylogger {

    private Mylogger mylogger;


    public proxyLogger(Mylogger logger){
        this.mylogger=logger;
    }

    @Override
    public void writerLog() { //增强的方法
        System.out.println("logger被代理了===前");
        mylogger.writerLog(); //需要增强的方法
        System.out.println("logger被代理了===后");
    }
}

测试:

public class staticProxyMain {


    public static void main(String[] args) {

        proxyLogger proxyLogger = new proxyLogger(new logger());

        proxyLogger.writerLog();

    }


}

结果:

logger被代理了===前
写入日志。
logger被代理了===后
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。