重要的设计原则
- 面向接口编程,不是面向实现.是优雅的,可扩展代码的第一步.
- 指责单一原则.每个类都应该只有一个单一的功能,并且该功能应该由这个类完全封装起来.
- 对修改关闭,对扩展开放.
简单工厂模式
public class FoodFactory {
public static Food makeFood(String name){
if(name.equals("noodle")){
Food noodles=new LanZhouNoodle();
return noodles;
}else if(name.equals("chicken")){
Food chicken=new HuangMenChinken();
return chicken;
}
}
}
其中LanZhouNoodle和HuangMenChicken都继承自Food
一个工厂类里面有一个静态方法,根据不同的参数返回不同的派生自同一个父类(或实现自同一接口)的实例对象.
符合指责单一原则,只负责生产对象.
工厂模式
public interface FoodFactory {
Food makeFood(String name);
}
public class ChineseFoodFactory implements FoodFactory{
@Override
public Food makeFood(String name){
if(name.equals("A")){
return new ChineseFoodA();
}else if(name.equals("B")){}
return new ChineseFoodB();
}
}
public class AmericanFoodFactory implements FoodFactory{
@Override
public Food makeFood(String name){
if(name.equals("A")){
return new AmericanFoodA();
}else if(name.equals("B")){}
return new AmericanFoodB();
}
}
其中ChineseFoodFactoryA,ChineseFoodFactoryB,AmericanFoodA,AmericanFoodB都派生自Food
使用时
public class App{
public static void main(String[] args) {
FoodFactory factory=new ChineseFoodFactory();
factory.makeFood("A");
FoodFactory factory=new AmericanFoodFactory();
factory.makeFood("A");
}
}
虽然都是调用makeFood(“A”) 但是不同工厂生产出来的对象不同.
先选取合适的工厂,然后通过该工厂来生产对象.
抽象工厂模式
当涉及到产品族的时候就需要抽象工厂模式
比如电脑是由很多零件组成,将cpu和主板进行抽象,然后cpu由cpuFactory生产,主板由MainBoardFactory生产,然后再将cpu和主板组合在一起.但是可能intel的cpu和AMD的主板不能兼容使用,所以就需要抽象工厂模式,直接定义电脑工厂,每个工厂负责生产cpu和主板所有的设备.
public interface ComputorFactory{
public CPU makeCPU();
public MainBoard makeMainBoard();
}
public class IntelFactory implements ComputorFactory{
public CPU makeCPU(){
return new IntelCPU();
}
public MainBoardFactory makeMainBoard(){
return new IntelMainBoard();
}
}
使用时
ComputorFactory factory = new IntelFactory();
factory.makeCPU();
factory.makeMainboard();
单例模式
饿汉模式
public class Hsingleton {
//将构造设为私有
private Hsingleton(){};
//创建私有静态实例,这个类第一次使用的时候就会进行创建
private static Hsingleton instance =new Hsingleton();
public static Hsingleton getInstance(){
return instance;
}
}
饱汉模式
public class Hsingleton {
//将构造设为私有
private Hsingleton(){};
//创建私有静态实例,这个类第一次使用的时候就会进行创建,用volatile修饰
private static volatile Hsingleton instance =null;
public static Hsingleton getInstance(){
if(instance==null){
//加锁
synchronized(Hsingleton.class){
//必须判断,不然有并发错误
if(instance==null){
instance=new Hsingleton();
}
}
}
return instance;
}
}
嵌套类
public class Singleton {
private Singleton(){}
//嵌套类可以使用外部类的静态属性和静态方法
private static class Holder{
private static Singleton instance=new Singleton();
}
public static Singleton getInstance(){
return Holder.instance;
}
}
建造者模式
public class Person {
//姓名 -required(必写)
private final String name;
//性别-required(必写)
private final String gender;
//年龄
private int age;
//省份证号
private String id;
public static class newBuilder{
//姓名 -required
private String name;
//性别-required
private String gender;
//年龄
private int age;
//省份证号
private String id;
public newBuilder setAge(int age){
this.age = age;
return this;
}
public newBuilder setId(String id){
this.id = id;
return this;
}
public newBuilder(String name,String gender){
this.name = name;
this.gender = gender;
}
public Person build(){
return new Person(this);
}
}
//外部类的私有构造函数
private Person(newBuilder builder){
this.name = builder.name;
this.gender = builder.gender;
this.age = age;
this.id = id;
}
}
创建对象时
Person p = new Person.newBuilder("miracle","male").setAge(18).build();
Person p = new Person.newBuilder("miracle","male").setAge(18).setId("1877551230").build();
思路
- 我们用builder方式创建对象时,用到了静态的内部类,内部类可以访问外部类的所有属性和方法
- 为外部类写一个私有的构造方法,就不能直接用外部类用new的方式来创建对象
- 所以用外部类打点内部类的方式先new出内部类对象,通过设置内部类的构造方法限定必须要输入的属性值;然后用内部类调用build()方法,返回一个以子类作为参数的Person类类型,内部类就通过私有的外部类构造器创建了一个新的对象
- 因为子类set方法的返回值都是子类的类类型,所以可以继续设置属性
优点
- 成员变量可以是final类型,通过设置构造函数来要求必须输入
- 对象状态连续,创建时就赋值,更加清晰
总结
- 外部类构造函数私有,且参数为静态内部类,使用静态内部类的变量为构建类逐一赋值
- 静态内部类拥有外部类相同的属性
- 为每一个属性写一个setter方法,返回的是当前Builder对象
- 最后提供一个方法build方法,new出来一个构建类的对象,参数是当前的Builder对象