网站加速代码,网站建设技术工具,net网站开发,网站云服务器1.1 炒菜没放盐 中餐#xff0c;老板需要每次炒菜#xff0c;每次炒出来的味道都有可能不同。麦当劳、肯德基这些不过百年的洋快餐却能在有千年饮食文化的中国发展的那么好呢#xff1f;是因为你不管何时何地在哪里吃味道都一样#xff0c;而鱼香肉丝在我们中餐却可以吃出上…1.1 炒菜没放盐 中餐老板需要每次炒菜每次炒出来的味道都有可能不同。麦当劳、肯德基这些不过百年的洋快餐却能在有千年饮食文化的中国发展的那么好呢是因为你不管何时何地在哪里吃味道都一样而鱼香肉丝在我们中餐却可以吃出上完口味来。 依赖倒转原则抽象不应该依赖细节细节应该依赖于抽象由于我们要吃的菜都依赖于厨师这样的细节所以我们就很被动。 好那再想想老麦老肯他们的产品味道是由什么决定的 我知道那是由他们的工作流程决定的由于他们制定了非常规范的工作流程原料放多少加热几分钟都有严格规定估计放多少盐都是用克来计量的。而这个工作流程是在所有的门店都必须要遵照执行的所以我们吃到的东西不管在哪在什么时候味道都一样。这里我们要吃的食物都依赖工作流程。不过工作流程好像还是细节呀。 对工作流程也是细节我们去快餐店消费我们用不用关心他们的工作流程当然是不用我们更关心的是是否好吃。你想如果老肯发现鸡翅烤得有些焦他们会调整具体的工作流程中的烧烤时间如果新加一种汉堡做法都相同只是配料不相同工作流程是不变的只是加了一种具体产品而已这里工作流程怎么样 对这里工作流程可以是一种抽象的流程具体放什么配料、烤多长时间等细节依赖于这个抽象。
1.2 建造小人一
建造小人要求要有头、身体、两手、两脚就可以了
package code.chapter13.builder1;
import java.awt.Graphics;
import javax.swing.JFrame;class Test extends JFrame {public Test() {setSize(400, 400);setDefaultCloseOperation(EXIT_ON_CLOSE);setLocationRelativeTo(null);}public void paint(Graphics g) {//瘦小人g.drawOval(150, 120, 30, 30); //头g.drawRect(160, 150, 10, 50); //身体g.drawLine(160, 150, 140, 200); //左手g.drawLine(170, 150, 190, 200); //右手g.drawLine(160, 200, 145, 250); //左脚g.drawLine(170, 200, 185, 250); //右脚//胖小人g.drawOval(250, 120, 30, 30); //头g.drawOval(245, 150, 40, 50); //身体g.drawLine(250, 150, 230, 200); //左手g.drawLine(280, 150, 300, 200); //右手g.drawLine(260, 200, 245, 250); //左脚g.drawLine(270, 200, 285, 250); //右脚}public static void main(String[] args) {new Test().setVisible(true);}
}这样的话有可能少画了一条腿或者一条胳膊就像厨师有可能忘记放盐。
1.3 建造小人二
建两个类一个廋人的类一个胖子的类不管谁都可以调用它
package code.chapter13.builder2;
import java.awt.Graphics;
import javax.swing.JFrame;class Test extends JFrame {public Test() {setSize(400, 400);setDefaultCloseOperation(EXIT_ON_CLOSE);setLocationRelativeTo(null);}public void paint(Graphics g) {//初始化瘦小人建造者类PersonThinBuilder gThin new PersonThinBuilder(g);gThin.build();//画瘦小人//初始化胖小人建造者类PersonFatBuilder gFat new PersonFatBuilder(g);gFat.build();//画胖小人}public static void main(String[] args) {new Test().setVisible(true);}
}//瘦小人建造者
class PersonThinBuilder {private Graphics g;public PersonThinBuilder(Graphics g){this.gg;}public void build(){g.drawOval(150, 120, 30, 30); //头g.drawRect(160, 150, 10, 50); //身体g.drawLine(160, 150, 140, 200); //左手g.drawLine(170, 150, 190, 200); //右手g.drawLine(160, 200, 145, 250); //左脚g.drawLine(170, 200, 185, 250); //右脚}
}//胖小人建造者
class PersonFatBuilder {private Graphics g;public PersonFatBuilder(Graphics g){this.gg;}public void build(){g.drawOval(250, 120, 30, 30); //头g.drawOval(245, 150, 40, 50); //身体g.drawLine(250, 150, 230, 200); //左手g.drawLine(280, 150, 300, 200); //右手g.drawLine(260, 200, 245, 250); //左脚g.drawLine(270, 200, 285, 250); //右脚}
}
如果再增加一个高个子的小人也有可能不小心最好的办法是规定凡是建造小人都必须要有头和身体以及两手两脚。
1.4 建造者模式 如果你需要将一个复杂对象的构建与它的表示分离使得同样的构建过程可以创建不同的表示的意图时我们需要应用于一个设计模式建造者模式Builder又叫生成器模式。建造者模式可以将一个产品的内部表象与产品的生成过程分割开来从而可以使一个建造过程生成具有不同的内部表象的产品对象。如果我们用了建造者模式那么用户就只需指定需要建造的类型就可以得到它们而具体建造的过程和细节就不需要知道了。 建造者模式Builder将一个复杂对象的构建与它的表示分离使得同样的构建过程可以创建不同的表示。DP 那怎么用建造者模式呢 一步一步来首先我们要画小人都需要画什么 头、身体、左手、右手、左脚、右脚。 对的所以我们先定义一个抽象的建造人的类来把这个过程给稳定住不让任何人遗忘当中的任何一步。 然后我们需要建造一个瘦的小人则让这个瘦子类去继承这个抽象类那就必须去重写这些抽象方法了。否则编译器也不让你通过。 当然胖人或高个子其实都是用类似的代码去实现这个类就可以了。 这样我在客户端要调用时还是需要知道头身手脚这些方法呀没有解决问题。小菜不解地问。 别急我们还缺建造者模式中一个很重要的类指挥者Director用它来控制建造过程也用它来隔离用户与建造过程的关联。 你看到没有PersonDirector类的目的就是根据用户的选择来一步一步建造小人而建造的过程在指挥者这里完成了用户就不需要知道了而且由于这个过程每一步都是一定要做的那就不会让少画了一只手少画一条腿的问题出现了。 代码结构图如下。 package code.chapter13.builder3;
import java.awt.Graphics;
import javax.swing.JFrame;class Test extends JFrame {public Test() {setSize(400, 400);setDefaultCloseOperation(EXIT_ON_CLOSE);setLocationRelativeTo(null);}public void paint(Graphics g) {PersonBuilder gThin new PersonThinBuilder(g);PersonDirector pdThin new PersonDirector(gThin);pdThin.CreatePerson();PersonBuilder gFat new PersonFatBuilder(g);PersonDirector pdFat new PersonDirector(gFat);pdFat.CreatePerson();}public static void main(String[] args) {new Test().setVisible(true);}
}//抽象的建造者类
abstract class PersonBuilder {protected Graphics g;public PersonBuilder(Graphics g){this.g g;}public abstract void buildHead(); //头public abstract void buildBody(); //身体public abstract void buildArmLeft(); //左手public abstract void buildArmRight(); //右手public abstract void buildLegLeft(); //左脚public abstract void buildLegRight(); //右脚
}//瘦小人建造者
class PersonThinBuilder extends PersonBuilder {public PersonThinBuilder(Graphics g){super(g);}public void buildHead(){g.drawOval(150, 120, 30, 30); //头}public void buildBody(){g.drawRect(160, 150, 10, 50); //身体}public void buildArmLeft(){g.drawLine(160, 150, 140, 200); //左手}public void buildArmRight(){g.drawLine(170, 150, 190, 200); //右手}public void buildLegLeft(){g.drawLine(160, 200, 145, 250); //左脚}public void buildLegRight(){g.drawLine(170, 200, 185, 250); //右脚 }
}//胖小人建造者
class PersonFatBuilder extends PersonBuilder {public PersonFatBuilder(Graphics g){super(g);}public void buildHead(){g.drawOval(250, 120, 30, 30); //头}public void buildBody(){g.drawOval(245, 150, 40, 50); //身体}public void buildArmLeft(){g.drawLine(250, 150, 230, 200); //左手}public void buildArmRight(){g.drawLine(280, 150, 300, 200); //右手}public void buildLegLeft(){g.drawLine(260, 200, 245, 250); //左脚}public void buildLegRight(){g.drawLine(270, 200, 285, 250); //右脚}
}//指挥者
class PersonDirector{private PersonBuilder pb;//初始化时指定需要建造什么样的小人public PersonDirector(PersonBuilder pb){this.pbpb;}//根据用户的需要建造小人public void CreatePerson(){pb.buildHead(); //头pb.buildBody(); //身体pb.buildArmLeft(); //左手pb.buildArmRight(); //右手pb.buildLegLeft(); //左脚pb.buildLegRight(); //右脚}
} 哈我明白了那客户端的代码我来写吧。应该也不难实现了。 试想一下我如果需要增加一个高个子和矮个子的小人我们应该怎么做 加两个类一个高个子类和一个矮个子类让它们都去继承PersonBuilder然后客户端调用就可以了。但我有个问题如果我需要细化一些比如人的五官手的上臂、前臂和手掌大腿小腿这些如何办呢 问得好这就需要权衡如果这些细节是每个具体的小人都需要构建的那就应该要加进去反之就没必要。其实建造者模式是逐步建造产品的所以建造者的Builder类里的那些建造方法必须要足够普遍以便为各种类型的具体建造者构造。
1.5 建造者解析
建造者模式Builder结构图 现在你看这张图就不会感觉陌生了。来总结一下Builder是什么 是一个建造小人各个部分的抽象类。 概括地说是为创建一个Product对象的各个部件指定的抽象接口。ConcreteBuilder是什么呢 具体的小人建造者具体实现如何画出小人的头身手脚各个部分。 对的它是具体建造者实现Builder接口构造和装配各个部件。Product当然就是那些具体的小人产品角色了Director是什么 指挥者用来根据用户的需求构建小人对象。 嗯它是构建一个使用Builder接口的对象。 那都是什么时候需要使用建造者模式呢 它主要用于创建一些复杂的对象这些对象内部子对象的建造顺序通常是稳定的但每个子对象本身的构建通常面临着复杂的变化。 哦是不是建造者模式的好处就是使得建造代码与表示代码分离由于建造者隐藏了该产品是如何组装的所以若需要改变一个产品的内部表示只需要再定义一个具体的建造者就可以了。 来来来我们来试着把建造者模式的基本代码推演一下以便有一个更宏观的认识。
1.6 建造者模式基本代码 Product类——产品类由多个部件组成。 Builder类——抽象建造者类确定产品由两个部件PartA和PartB组成并声明一个得到产品建造后结果的方法GetResult。 ConcreteBuilder1类——具体建造者类。 ConcreteBuilder2类——具体建造者类。 Director类——指挥者类。 客户端代码客户不需要知道具体的建造过程。
package code.chapter13.builder0;import java.util.ArrayList;public class Test {public static void main(String[] args){System.out.println(**********************************************); System.out.println(《大话设计模式》代码样例);System.out.println(); Director director new Director();Builder b1 new ConcreteBuilder1();Builder b2 new ConcreteBuilder2();//指挥者用ConcreteBuilder1的方法来建造产品director.construct(b1); //创建的是产品A和产品BProduct p1 b1.getResult();p1.show();//指挥者用ConcreteBuilder2的方法来建造产品director.construct(b2); //创建的是产品X和产品YProduct p2 b2.getResult();p2.show();System.out.println();System.out.println(**********************************************);}
}//产品类
class Product{ArrayListString parts new ArrayListString();//添加新的产品部件public void add(String part){parts.add(part);}//列举所有产品部件public void show(){for(String part : parts){System.out.println(part);}}
}//抽象的建造者类
abstract class Builder {public abstract void buildPartA(); //建造部件Apublic abstract void buildPartB(); //建造部件Bpublic abstract Product getResult(); //得到产品
}//具体建造者1
class ConcreteBuilder1 extends Builder {private Product product new Product();public void buildPartA(){product.add(部件A);}public void buildPartB(){product.add(部件B);}public Product getResult(){return product;}
}//具体建造者2
class ConcreteBuilder2 extends Builder {private Product product new Product();public void buildPartA(){product.add(部件X);}public void buildPartB(){product.add(部件Y);}public Product getResult(){return product;}
}//指挥者
class Director{public void construct(Builder builder){builder.buildPartA();builder.buildPartB();}
} 所以说建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式。