设计模式:创建型模式(一)

设计模式是什么,为什么要用设计模式

很久以来,我一直认为修房子和写代码是一样的道理都是相通的。我经常在建筑上面去寻找做软件的答案。我们中国有很多的超级工程,但是我时常认为软件也是超级工程。我喜欢建筑,同样我也喜欢写代码,当很多时候我在软件方面遇到我无法解释的问题,我都会等价的替换到建筑里面,然后去寻找相应的答案。

设计模式是什么,在我看来设计模式就是一套大家都这样做,这样开发的效率高,速度快,可以重用率高的一种代码的编码方式。在建筑行业里面国家会规定非常多的标准。只要工人在这个框架里面去修建,每一条都符合国家标准,那么最后修出来的房子一定是合格的。但是在IT行业,没有强行的标准去统一一些具体的规范,所以为了保证项目的质量,我们也必须的按照一定的规范去做。而设计模式就是这些规范里面很重要的一种。

为什么我们要用,既然有成型的而且是非常有用的,那么我们在这个过程中按照这种流程操作,不管是对开发者,项目本身以及用户而言都是非常好的标志。所以对于开发者而言了解设计模式是非常重要的,了解了设计模式,其实在平时的开发过程中在设计模式里已经可以找到很好的解决方案。

设计模式类型

设计模式总共有23种,这些模式可以分为3大类。

  • 创建型模式
  • 结构性模式
  • 行为型模式

本篇博客主要讲创建型模式的基本内容。

创建型模式

创建型模式应该是我们在编写代码当中使用最多的分类了,这些设计模式提供了一种在创建对象的同时隐藏创建的逻辑的方式,而不是使用new运算符来直接实例化对象。这些程序可以自己去判断如何实例化对象,这样在创建时可以更加的灵活和方便。

  • 工厂模式(Factory Pattern)
  • 抽象工厂模式(Abstract Factory Pattern)
  • 单例模式(Singleton Pattern)
  • 建造者模式(Builder Pattern)
  • 原型模式(Prototype Pattern)
工厂模式(Factory Pattern)
      在工厂模式中,我们创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
下面通过代码加上代码里的注释来表示,因为我觉得用文字很难直接描述。
//创建接口动物。拥有吃的功能
public interface Animal {
    void eat();
}
//创建Cat类,继承于Animal类。重写Animal类的eat方法。后面的Pig和Dog类一样。
public class Cat implements Animal {

    @Override
    public void eat() {
        System.out.println("Cat eat lanch");
    }
}
public class Dog implements Animal {

    @Override
    public void eat() {
        System.out.println("Dog eat lanch");
    }
}
public class Pig implements Animal {

    @Override
    public void eat() {
        System.out.println("Pig eat lanch");
    }
}
//创建工厂类来负责生产对象
public class AnimalFactory {

    public Animal getAnimal(String type){
        if(type == null){
            return null;
        }
        if(type.equalsIgnoreCase("cat")){
            return new Cat();
        }else if(type.equalsIgnoreCase("pig")){
            return new Pig();
        }else if(type.equalsIgnoreCase("dog")){
            return new Dog();
        }
        return null;
    }
}
public class Demo {

    public static void main(String[] args){
        AnimalFactory animalFactory=new AnimalFactory();
        Animal pig = animalFactory.getAnimal("pig");
        Animal dog = animalFactory.getAnimal("dog");
        Animal cat = animalFactory.getAnimal("cat");
        pig.eat();
        dog.eat();
        cat.eat();
    }
}
//运行Console框的输出内容
Pig eat lanch
Dog eat lanch
Cat eat lanch
分析一下。首先我们创建了Animal接口。然后创建了Pig,Dog和Cat三个类去实现了Animal的接口然后重写了eat的函数。最后创建了一个Animal工厂类来创建对象。在Demo类里面我们可以看到。我们先创建一个工厂的对象。然后后面的动物我们都不需要通过new来创建。只需要调用工厂类替我们创建我们想要创建的对象。从而隐藏了对象的创建细节。在我们有很多对象需要创建,而且创建过程很复杂的时候,就可以通过使用工厂模式来减少客户端的创建代码。

抽象工厂模式(Abstract Factory Pattern)
抽象工厂模式就是一个超级工厂可以创建很多个工厂,而每个工厂又可以去创建自己相应的类。在抽象工厂模式中,接口负责创建一个相关对象的工厂,不需要显示的指定他们的类,而每个工厂都能按照工厂模式提供对象。

//创建接口动物。拥有吃的功能
public interface Animal {
    void eat();
}
//创建Cat类,继承于Animal类。重写Animal类的eat方法。后面的Pig和Dog类一样。
public class Cat implements Animal {

    @Override
    public void eat() {
        System.out.println("Cat eat lanch");
    }
}
public class Dog implements Animal {

    @Override
    public void eat() {
        System.out.println("Dog eat lanch");
    }
}
public class Pig implements Animal {

    @Override
    public void eat() {
        System.out.println("Pig eat lanch");
    }
}
//创建颜色接口,用户fill功能
public interface Color {
    void fill();
}
public class Blue implements Color{

    @Override
    public void fill() {
        System.out.println("has blue color");
    }
}
public class Green implements Color{

    @Override
    public void fill() {
        System.out.println("has green color");
    }

}
public class Red implements Color{

    @Override
    public void fill() {
        System.out.println("has red color");
    }
}
//创建抽象工厂类。拥有创建颜色和动物两种功能
public abstract class AbstractFactory {

    abstract Color getColor(String color);
    abstract Animal getAnimal(String animal);
}
//动物工厂
public  class AnimalFactory extends AbstractFactory{

    @Override
    public Animal getAnimal(String shapeType){
        if(shapeType==null){
            return null;
        }
        if(shapeType.equalsIgnoreCase("pig")){
            return new Pig();
        }else if(shapeType.equalsIgnoreCase("cat")){
            return new Cat();
        }else if(shapeType.equalsIgnoreCase("dog")){
            return new Dog();
        }
        return null;
    }


    @Override
    Color getColor(String color){
        return null;
    }

}
//颜色工厂
public class ColorFactory extends AbstractFactory{

    @Override
    Color getColor(String color) {
        if(color==null){
            return null;
        }
        if(color.equalsIgnoreCase("red")){
            return new Red();
        }else if(color.equalsIgnoreCase("green")){
            return new Green();
        }else if(color.equalsIgnoreCase("blue")){
            return new Blue();
        }
        return null;
    }

    @Override
    Animal getAnimal(String animal) {
        return null;
    }
}
//工厂的Provider。用来提供创建工厂
public class FactoryProvider {

    public static AbstractFactory getFactory(String factory){
        if(factory.equalsIgnoreCase("animal")){
            return new AnimalFactory();
        }else if(factory.equalsIgnoreCase("color")){
            return new ColorFactory();
        }
        return null;
    }
}
public class Demo {

    public static void main(String[] args){
       //获取工厂
        AbstractFactory animalFactory = FactoryProvider.getFactory("animal");
        Animal pig = animalFactory.getAnimal("pig");
        pig.eat();

        AbstractFactory colorFactory = FactoryProvider.getFactory("color");
        Color red = colorFactory.getColor("red");
        red.fill();

    }
}
分析:首先创建了AbstractFactory类,然后通过FactoryProvider来创建抽象工厂。抽象工厂再通过输入类型来产生相应的对象。
单例模式(Singleton Pattern)
这种模式设计到单一的类,改类负责创建自己的实例,并且保证只有单个对象被创建。这个类提供了访问其唯一对象的方式,可以直接访问,不需要实例化改对象。
注意:1.单例类只能有一个实例。2.单例类必修自己创建自己的实例。3.单例类必须给所有其他的对象提供这一实例。
public class SingleObject {

    private static SingleObject  instance =new SingleObject();

    //私有构造函数
    private SingleObject(){}

    public static SingleObject getInstance(){

        return instance;
    }

    public void showMessage(){
        System.out.print("Show Message");
    }
}
   public static void main(String[] args){

        //编译错误,构造函数是private的无法直接new对象
        //SingleObject object=new SingleObject();

        SingleObject object= SingleObject.getInstance();

        SingleObject object1 = SingleObject.getInstance();
        if(object.equals(object1)){
            System.out.println(true);
        }
        object.showMessage();
    }
我们看到就是使用两个Object 去创建SingleObject。但是使用equals比对发现结果是true。表示只能有一个对象。保证了单例模式。
注意:现在创建单例模式的最好方式是使用枚举类创建。
建造者模式(Builder Pattern)
建造者模式是使用多个简单的对象一步一步的构建成一个复杂的对象,一个Builder类会一步一步的构造最终的对象,该builder类是独立于其他对象的。
public class Food {

    //菜
    private String greens;

    //肉
    private String meat;

    //调料
    private String flavour;

    public String getGreens() {
        return greens;
    }

    public void setGreens(String greens) {
        this.greens = greens;
    }

    public String getMeat() {
        return meat;
    }

    public void setMeat(String meat) {
        this.meat = meat;
    }

    public String getFlavour() {
        return flavour;
    }

    public void setFlavour(String flavour) {
        this.flavour = flavour;
    }


    public void print(){
        System.out.println("肉食:"+getMeat()+" 配菜"+getGreens()+" 调料"+getFlavour());
    }
}
//菜谱抽象类
public abstract class FoodBuilder {

    Food food=new Food();

    public abstract void buildGreens();

    public abstract void buildMeats();

    public abstract void buildFlavours();

    public Food getFood(){
        return food;
    }

}
//套餐A的菜谱
public class FoodABuilder extends FoodBuilder{

    @Override
    public void buildGreens() {
        food.setGreens("土豆");
    }

    @Override
    public void buildMeats() {
        food.setMeat("猪肉");
    }

    @Override
    public void buildFlavours() {
        food.setFlavour("放辣椒");
    }
}
//套餐B的菜谱
public class FoodBBuilder extends FoodBuilder{
    @Override
    public void buildGreens() {
        food.setGreens("西红柿");
    }

    @Override
    public void buildMeats() {
        food.setMeat("鸡肉");
    }

    @Override
    public void buildFlavours() {
        food.setFlavour("醋");
    }
}
//厨师,根据输入的菜谱进行炒菜
public class Chef {

    private FoodBuilder foodBuilder;

    public void setFoodBuilder(FoodBuilder foodBuilder){
        this.foodBuilder = foodBuilder;
    }

    //根据foodBuilder创建食物
    public Food fry(){
        foodBuilder.buildFlavours();
        foodBuilder.buildGreens();
        foodBuilder.buildMeats();
        return foodBuilder.getFood();
    }

}

public class Demo {

    public static void main(String[] args){
        //创建厨师
        Chef chef=new Chef();
        //创建菜谱
        FoodABuilder foodABuilder = new FoodABuilder();

        //把菜谱交给厨师
        chef.setFoodBuilder(foodABuilder);

        //厨师炒菜给客户
        Food food = chef.fry();

        food.print();

    }
}
分析:在使用建造者模式的情况下,我们想要获取一个食物的对象。我们先创建厨师和菜单。然后将菜单交给厨师。厨师就会按照菜单的要求炒出我们想要吃的食物。虽然现在我们的Demo例子看起来是New一个Food对象,然后直接设置属性很简单。我们这样操作还添加了很多的其他的对象。但是当我们的食物的做法很复杂。而且菜谱很多的时候。使用建造者模式就可以拥有非常大的优势了。
原型模式(Prototype Pattern)
原型模式用于创建重复的对象,同时又能保证性能。这种模式实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大的时候。采用这种模式可以减少资源的消耗。
public class Prototype implements Cloneable{

    public Prototype clone(){
        Prototype prototype = null;
        try {
            prototype = (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return prototype;
    }

}

public class ConcretePrototype extends Prototype{

    public void show(){
        System.out.println("实现Prototype类");
    }
}

public class Demo {

    public static void main(String[] args){
        ConcretePrototype concretePrototype=new ConcretePrototype();
        for(int i=0;i<100;i++){
            ConcretePrototype clonePrototype = (ConcretePrototype)concretePrototype.clone();
            clonePrototype.show();
            System.out.println(clonePrototype.hashCode());
        }
    }
}

实现Prototype类
1639705018
实现Prototype类
1627674070
实现Prototype类
1360875712
实现Prototype类
1625635731
实现Prototype类
1580066828
分析:从输出结果我们可以看到,Clone的对象的的show()方法是正确的,Hashcode的值也是不一样的。说明clone成功。
注:本博客所用的实例代码都会放在Github供大家下载学习。
地址:https://github.com/standup-jb/DesignPattern.git 
知乎主页:点击关注我知乎
如果可以愿意分享自己的见解或者添加更多更好的实例代码,可以联系我。谢谢。















  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值