设计模式

在之前的简单工厂模式中,虽然能够比较好的处理封装创造对象的过程,但是明显的,每当要添加一种新的面包时候,就需要修改简单类工厂,增加case分支(或者是if else分支),这样最大的问题就是不满足于开闭原则。

工厂模式-简单工厂模式的升级版

GOF对于工厂方法模式的定义是:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法将一个类的实例化延迟了他的子类。

来看他的结构图

屏幕快照 2018-10-17 下午4.25.34.png

简单来说,每个工厂负责实例化本工厂产生的产品,在客户端编写代码时候都按照父类(接口)来进行编写,因此,无论实例化了哪一个类,都可以直接替换父类(依赖倒转原则),从而达到可以复用代码的目的。

代码修改

本代码是在简单工厂模式的基础上修改而来的。简单工厂,请移步前一篇文章。

//首先来看工厂的接口
public interface IFactory{

    BreadMaker CreateBread();
}
//不同的面包工厂建立一个具体的工厂方法来实现这个借口
public class BlackBreadFactory implements IFactory{

    //覆盖父类的抽象方法
    public BreadMaker CreateBread(){

        return new BlackBread();
    }
}

public class HoneyBreadFactory implements IFactory{

    //覆盖父类的抽象方法
    public BreadMaker CreateBread(){

        return new HoneyBread();
    }
}



/*

客户端的代码实现
*/
public static void main(String[] args){

    BreadMaker breadMaker;
    System.out.Println("小面的面包店开业了!");

    //顾客上门来买面包,要黑面包
    IFactory breadFactory = new BlackBreadFactory();
    breadMaker = breadFactory.CreateBread();
    breadMaker.getBread();

}

需要注意的是:
在客户端中,如果需要创建一个对象的话,那么首先实例化一个工厂(子工厂),接着用这个工厂去创造相应的对象就可以了。

工厂模式和简单工厂模式的对比

简单工厂模式违反了开放-封闭原则,但是保持了封装对象创建的过程。
可以说工厂模式就是简单工厂模式的升级版,是简单工厂的进一步抽象和推广。但是工厂模式也有缺点:每增加一个产品,就要相应的添加一个产品工厂类,增大了额外的开发量。

工厂模式适用于以下三种情况

  • 当一个类不知道他所创建的对象的类的时候,比如说要创建一个白面包的对象,但是并不知道他的类是WhiteBread。
  • 当一个类希望由他的子类来指定它所创建的对象的时候。
  • 当类创建的对象的职责委托给多个帮助子类中的一个,并且希望将哪一个帮助子类是代理者这一信息局部化的时候。

如何选择

要取决于具体的应用,就像是两个模式的名称就可以看出来,对于一些比较简单的应用,“产品”类比较少的时候,使用简单工厂模式就可以满足要求,而对于“产品”比较丰富的应用,过多的分支不利于程序的维护,这时候应该选择工厂模式来降低程序的维护量。

简单工厂模式

设计模式

正在处理

介绍

简单工厂模式虽然不在GOF的23中设计模式中,却被广泛的应用。简单工厂模式的最大的优点是除去了客户端对于具体产品的依赖,因为工厂类中包含了需要的逻辑判断。虽然简单工厂模式违反了开闭原则,但是保持了封装对象创建的优点。

简单工厂模式模式是由一个工厂对象决定创建出哪一种产品类的实例。可以理解为不同工厂模式的一个特殊实现。

代码实现

面包师和面包类

//面包师的代码,作为父类
public class BreadMaker{

    public void GetBread(){

        //Nothing to do;
    }
}
//黑面包代码
public class BlackBread{

    //覆盖父类抽象方法
    public void GetBread(){

        System.out.println("烤出了黑面包");
    }
}
//蜂蜜面包的代码

public class HoneyBread{

    //覆盖父类抽象方法
    public void GetBread(){

        System.out.println("烤出了蜂蜜面包");
    }
}

面包工厂代码

//工厂
public class BreadFactory{

    public static BreadMaker MakeBread(int breadType){

        BreadMaker beradMaker = null;
        //选择面包的类型
        switch(breadType){

            case 1:
                beradMaker = new BlackBread();
                break;
            case 2:
                BreadMaker = new HoneyBread();
                break;
            default:
                break;

        }
        return beradMaker;
    }

}

客户端代码

//客户端代码
public static void main(String[] args){

    BreadMaker beradMaker;
    System.out.println("面包店要开业了");
    System.out.println("顾客要黑面包");
    beradMaker = BreadFactory.MakeBread(1);
    System.out.println("顾客要蜂蜜面包");
    beradMaker = BreadFactory.MakeBread(2);
}

简单工厂模式存在的问题

不符合开闭原则
如果增加一种新面包的话,需要增加一个新的面包类,同时也要修改简单工厂类,增加Case分支,很明显对外拓展的同时,对外修改也开放了。
而解决这个问题的办法就是—工厂方法

为什么我们要用UWP

大家知道在Windows10中应用商店程序是特色,它因为简洁,优美,易于安装卸载受到了很多人的热爱。
我们今天就是要把网页做成一个UWP应用,并且在本机中使用它!
按照本篇教程走,你最终可以得到一个类似于这样的UWP应用。

效果图.PNG

在这里我们以幕布为例。

幕布是一款优秀的笔记应用,在美观的同时保持了强大的功能。
更可以一键生成思维导图,演示等等
如果你对幕布感兴趣,可以点击这里
通过本链接注册成为新用户,可以免费获取15天的高级账户。

  • 首先找到你要做成UWP的网页,然后尽可能的去登陆他。

    在这里我们找到幕布的首页,点击登陆。
    
  • 转到你需要应用默认的页面,然后复制他的地址。

    将地址栏中的地址复制出来。
  • 在VS中新建一个空白模板的UWP。
  • 在Main 中添加一个web View 。并且设置source为我们之前复制的地址。
  • 执行他! 恭喜,你已经完成了。

Docker简介

Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的LInux机器上,也可以实现使用沙盒机制,相互之间不会有任何接口。

使用docker安装Hadoop

之前曾经分享过如何使用docker安装oracle,今天我们要使用docker安装Hadoop。
一般的在进行环境搭建的时候,我们都会有以下两种方案:

1.采用多个主机
2.使用虚拟机
但是这两种方法都很具有局限性。

第一种方法,我们往往找不到那么多的主机,想要让Hadoop有意义,至少需要3个主机。
第二种方法,对于宿主机的要求非常的高,如果没有很高的配置的话,费尽千辛万苦,到最后也基本上跑不动。
而且步骤繁琐,往往还没有安装到Hadoop,就耗费完了精力。

详细步骤 项目地址

  • pull docker image
sudo docker pull kiwenlau/hadoop:1.0
  • clone GitHub repository
git clone https://github.com/kiwenlau/hadoop-cluster-docker
  • create Hadoop network
sudo docker network create --driver=bridge hadoop
  • start container
cd hadoop-cluster-docker
sudo ./start-container.sh

output :

start hadoop-master container...
start hadoop-slave1 container...
start hadoop-slave2 container...
root@hadoop-master:~# 
  • start hadoop
./start-hadoop.sh
  • run wordcount
./run-wordcount.sh

output

input file1.txt:
Hello Hadoop

input file2.txt:
Hello Docker

wordcount output:
Docker    1
Hadoop    1
Hello    2

给已存在的元素绑定事件时可以直接写:

$(".class a").click(function(){   })

但是对于动态生成并append()到页面上的元素来说,就不能直接用上面的方法来绑定事件了。

在Jquery 1.7之前我们可以通过live()和delegate()来解决:

1.live()方法

语法:$(selector).live(event,data,function)

$(".class a").live("click",function(){   })

但是在Jquery1.7版本中就不推荐使用live()方法了,在1.9版本中live()方法被移除了,用on()方法来代替。

官方原文档说法如下:The live() method was deprecated in jQuery version 1.7, and removed in version >1.9. Use the on() method instead.

2.delegate()方法

语法:$(selector).delegate(childSelector,event,data,function)

$(".class").delegate("a","click",function(){  })

delegate()方法在jQuery 3.0版本中就不推荐用了,只是还没有被删除而已,推荐用on()方法来代替。

官方原文档说法如下:The delegate() method was deprecated in version 3.0. Use the on() method >instead.

现在推荐的方法是on():

3.on()方法

语法:$(selector).on(event,childSelector,data,function,map)

$(".class").on("click","a",function(){ })

继jQuery1.7之后,on()方法替代了bind(), live() 和 delegate() 方法。on()方法可以给当前元素和未来元素绑定事件。

childSelector项是可选的,如果没有childSelector项的话,只能给被选元素(已存在的元素)绑定事件,不能给未来元素(后续动态生成的元素)绑定事件;

用off()方法解除事件的绑定,如果绑定的事件只执行一次,则用one()方法。

现在知道了怎么给未来元素绑定事件,那么原理是什么呢?

给未来元素绑定事件的原理其实是事件委托,把事件绑定在未来元素的父元素上,然后通过父元素找到子元素触发该事件。