设计模式是什么,为什么要用设计模式
很久以来,我一直认为修房子和写代码是一样的道理都是相通的。我经常在建筑上面去寻找做软件的答案。我们中国有很多的超级工程,但是我时常认为软件也是超级工程。我喜欢建筑,同样我也喜欢写代码,当很多时候我在软件方面遇到我无法解释的问题,我都会等价的替换到建筑里面,然后去寻找相应的答案。
设计模式是什么,在我看来设计模式就是一套大家都这样做,这样开发的效率高,速度快,可以重用率高的一种代码的编码方式。在建筑行业里面国家会规定非常多的标准。只要工人在这个框架里面去修建,每一条都符合国家标准,那么最后修出来的房子一定是合格的。但是在IT行业,没有强行的标准去统一一些具体的规范,所以为了保证项目的质量,我们也必须的按照一定的规范去做。而设计模式就是这些规范里面很重要的一种。
为什么我们要用,既然有成型的而且是非常有用的,那么我们在这个过程中按照这种流程操作,不管是对开发者,项目本身以及用户而言都是非常好的标志。所以对于开发者而言了解设计模式是非常重要的,了解了设计模式,其实在平时的开发过程中在设计模式里已经可以找到很好的解决方案。
设计模式类型
设计模式总共有23种,这些模式可以分为3大类。
- 创建型模式
- 结构性模式
- 行为型模式
本篇博客主要讲创建型模式的基本内容。
创建型模式
创建型模式应该是我们在编写代码当中使用最多的分类了,这些设计模式提供了一种在创建对象的同时隐藏创建的逻辑的方式,而不是使用new运算符来直接实例化对象。这些程序可以自己去判断如何实例化对象,这样在创建时可以更加的灵活和方便。
- 工厂模式(Factory Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 单例模式(Singleton Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype 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来创建。只需要调用工厂类替我们创建我们想要创建的对象。从而隐藏了对象的创建细节。在我们有很多对象需要创建,而且创建过程很复杂的时候,就可以通过使用工厂模式来减少客户端的创建代码。
//创建接口动物。拥有吃的功能
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来创建抽象工厂。抽象工厂再通过输入类型来产生相应的对象。
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。表示只能有一个对象。保证了单例模式。
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对象,然后直接设置属性很简单。我们这样操作还添加了很多的其他的对象。但是当我们的食物的做法很复杂。而且菜谱很多的时候。使用建造者模式就可以拥有非常大的优势了。
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成功。