GOF23(java设计模式)--创建型模式

单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式

一、单例模式
作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。
五种写法:饿汉模式、懒汉模式、双重检测锁、静态内部类实现延迟加载、枚举类实现单例(不细讲了,具体参考我的另一篇文章https://www.jianshu.com/p/e86833bee429)
二、简单工厂模式
2.1、作用:用来生产同一等级结构中的任意产品。(对于增加新的产品,需要修改已有代码)
2.2、缺点:对于增加新产品无能为力!不修改代码的话,是无法扩展的,不完全满足开闭原则(如下面的例子,如果再增加华为电脑,则必须修改工厂类的代码)
2.3、UML图:

GOF23(java设计模式)--创建型模式_第1张图片
简单工厂模式.png

2.4、示例:

//电脑接口
public interface Computer {
    public void play();
}
//联想电脑类
class LenovoComputer implements Computer{
    public void play() {
        System.out.println("我是联想电脑");
    }
}
//苹果电脑类
class MacComputer implements Computer{
    public void play() {
        System.out.println("我是苹果电脑");
    }
}
--------------------------------------------------------------------------------
//简单工厂类,类方法一般为静态的,所以也称为静态工厂
public class SimpleFactory {
    public static Computer createComputer(String type){
        if(type.equalsIgnoreCase("mac")){
            return new MacComputer();
        }else{
            return new LenovoComputer();
        }
    }
    
    public static Computer createLenovoComputer(){
        return new LenovoComputer();
    }
    
    public static Computer createMacComputer(){
        return new MacComputer();
    }
}
--------------------------------------------------------------------------------
//客户端
public class Client {
    public static void main(String[] args) {
        SimpleFactory simpleFactory = new SimpleFactory();
        Computer c1 = simpleFactory.createComputer("mac");
        Computer c2 = simpleFactory.createLenovoComputer();
        c1.play();
        c2.play();
    }
}

三、工厂方法模式
3.1、作用:为了避免简单工厂模式的缺点,不完全满足开闭原则,而设计的。工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类
3.2、缺点:除了是满足开闭原则外,从结构复杂度、代码复杂的、客户端编程难度、管理上的难度上看,工厂方法相比简单工厂都要复杂,所以实际上,我们一般只会用简单工厂,很少会用到工厂方法模式
3.3、UML图:


GOF23(java设计模式)--创建型模式_第2张图片
工厂方法模式.png

3.4、示例:

//电脑接口
public interface Computer {
    public void play();
}
//联想电脑类
class LenovoComputer implements Computer{
    public void play() {
        System.out.println("我是联想电脑");
    }
}
//苹果电脑类
class MacComputer implements Computer{
    public void play() {
        System.out.println("我是苹果电脑");
    }
}
--------------------------------------------------------------------------------
//工厂接口
public interface FactoryMethod {
    public Computer createComputer();
}
//联想工厂
class LenovoComputerFactory implements FactoryMethod{
    public Computer createComputer() {
        return new LenovoComputer();
    }
}
//苹果工厂
class MacComputerFactory implements FactoryMethod{
    public Computer createComputer() {
        return new MacComputer();
    }
}
--------------------------------------------------------------------------------
//客户端
public class Client {
    public static void main(String[] args) {
        FactoryMethod factory1  = new LenovoComputerFactory();
        FactoryMethod factory2  = new MacComputerFactory();
        LenovoComputer c1 = (LenovoComputer) factory1.createComputer();
        MacComputer c2 = (MacComputer) factory2.createComputer();
        c1.play();
        c2.play();
    }
}

结论:由此看出,如果再加入一个华为的电脑,只需加入一个华为电脑的类和一个华为电脑工厂就可以了,不需要修改之前的任何代码,因此满足了开闭原则

四、抽象工厂模式
4.1、作用:用来生产不同产品族的全部产品,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
4.2、缺点:对于增加新的产品,无能为力;支持增加产品族(如在下面例子中,若再加入华为电脑,则需要新增华为电脑工厂类,并要修改每一个配件类,去新增产品配件,因此就不能满足开闭原则了)
4.3、UML图:


GOF23(java设计模式)--创建型模式_第3张图片
抽象工厂模式.png

4.4、示例:

//电脑类
public class Computer {
    private Engine engine;
    private Keyboard keyboard;
    private Mouse mouse;
    public Engine getEngine() {
        return engine;
    }
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
    public Keyboard getKeyboard() {
        return keyboard;
    }
    public void setKeyboard(Keyboard keyboard) {
        this.keyboard = keyboard;
    }
    public Mouse getMouse() {
        return mouse;
    }
    public void setMouse(Mouse mouse) {
        this.mouse = mouse;
    }
    public void play(){
        System.out.println(engine.getName()+keyboard.getName()+mouse.getName());
    };
}
//引擎类(为了简洁,此处没有用到接口,直接用名字代表不同的对象)
class Engine{
    private String name;
    public Engine(String name){this.name=name;}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//键盘类(为了简洁,此处没有用到接口,直接用名字代表不同的对象)
class Keyboard{
    private String name;
    public Keyboard(String name){this.name=name;}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//鼠标类(为了简洁,此处没有用到接口,直接用名字代表不同的对象)
class Mouse{
    private String name;
    public Mouse(String name){this.name=name;}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
--------------------------------------------------------------------------------
//抽象工厂接口
public interface AbstractFactory {
    public Computer createComputer();
}
//联想电脑工厂
class LenovoComputerFactory implements AbstractFactory{
    public Computer createComputer() {
        Computer c = new Computer();
        c.setEngine(new Engine("联想CPU"));
        c.setKeyboard(new Keyboard("联想键盘"));
        c.setMouse(new Mouse("联想鼠标"));
        return c;
    }
}
//苹果电脑工厂
class MacComputerFactory implements AbstractFactory{
    public Computer createComputer() {
        Computer c = new Computer();
        c.setEngine(new Engine("苹果CPU"));
        c.setKeyboard(new Keyboard("苹果键盘"));
        c.setMouse(new Mouse("苹果鼠标"));
        return c;
    }
}
--------------------------------------------------------------------------------
//客户端
public class Client {
    public static void main(String[] args) {
        AbstractFactory Lenovofactory = new LenovoComputerFactory();
        AbstractFactory Macfactory = new MacComputerFactory();
        Computer LenovoComputer = Lenovofactory.createComputer();
        Computer MacComputer = Macfactory.createComputer();
        LenovoComputer.play();
        MacComputer.play();
    }
}

五、建造者模式
5.1、作用:分离了对象子组件的单独构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况下使用。由于实现了构建和装配的解耦。不同的构建器,相同的装配,也可以做出不同的对象;相同的构建器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。
5.2、UML图:


GOF23(java设计模式)--创建型模式_第4张图片
建造者模式.png

5.3、示例:

//电脑类
public class Computer {
    private Engine engine;
    private Keyboard keyboard;
    private Mouse mouse;
    public Engine getEngine() {
        return engine;
    }
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
    public Keyboard getKeyboard() {
        return keyboard;
    }
    public void setKeyboard(Keyboard keyboard) {
        this.keyboard = keyboard;
    }
    public Mouse getMouse() {
        return mouse;
    }
    public void setMouse(Mouse mouse) {
        this.mouse = mouse;
    }
    public void play(){
        System.out.println(engine.getName()+keyboard.getName()+mouse.getName());
    };
}
//引擎类
class Engine{
    private String name;
    public Engine(String name){this.name=name;}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//键盘类
class Keyboard{
    private String name;
    public Keyboard(String name){this.name=name;}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//鼠标类
class Mouse{
    private String name;
    public Mouse(String name){this.name=name;}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
--------------------------------------------------------------------------------
//电脑构建接口
public interface ComputerBuilder {
    public Engine createEngine();
    public Keyboard createKeyBoard();
    public Mouse createMouse();
}
class realComputerBuilder implements ComputerBuilder{
    public Engine createEngine() {
        return new Engine("联想CPU");
    }
    public Keyboard createKeyBoard() {
        return new Keyboard("苹果键盘");
    }
    public Mouse createMouse() {
        return new Mouse("华为鼠标");
    }
}
--------------------------------------------------------------------------------
//电脑组装接口
public interface ComputerDirector {
    public Computer computerDirector(ComputerBuilder computerBuilder);
}
class realComputerDirector implements ComputerDirector{
    public Computer computerDirector(ComputerBuilder computerBuilder) {
        Computer c = new Computer();
        c.setEngine(computerBuilder.createEngine());
        c.setKeyboard(computerBuilder.createKeyBoard());
        c.setMouse(computerBuilder.createMouse());
        return c;
    }
}
--------------------------------------------------------------------------------
//客户端
public class Client {
    public static void main(String[] args) {
        ComputerBuilder computerBuilder = new realComputerBuilder();
        ComputerDirector computerDirector = new realComputerDirector(); 
        Computer c =computerDirector.computerDirector(computerBuilder);
        System.out.println(c.getEngine().getName()+""+c.getKeyboard().getName()+""+c.getMouse().getName()+"");
    }
}
--------------------------------------------------------------------------------
总结:如上代码,如果要生产不同型号的配件,只需要创建一个新的构造器类,需要组装成不同型号的电脑也只需要创建一个新的组黄器类,不需要修改之前的代码

六、原型模式(prototype)
6.1、作用:通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。它本身就是java中的克隆技术,以某个对象为原型,复制出新的对象。显然,新的对象具备原型对象的特点。优势有:效率高(直接克隆,避免了重新执行构造过程步骤) 。克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值。克隆出的对象的属性值完全和原型对象相同。并且克隆出的新对象改变不会影响原型对象。然后,再修改克隆对象的值。
6.2、重要知识点:克隆问题(浅克隆和深克隆,此处不详说,请另行查看我的文章:https://www.jianshu.com/p/d2783a7cf031)
6.3、UML图:

GOF23(java设计模式)--创建型模式_第5张图片
原型模式.png

6.4、示例:

//电脑类
public class Computer implements Serializable{
    private Engine engine;
    private Keyboard keyboard;
    private Mouse mouse;
    public Engine getEngine() {
        return engine;
    }
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
    public Keyboard getKeyboard() {
        return keyboard;
    }
    public void setKeyboard(Keyboard keyboard) {
        this.keyboard = keyboard;
    }
    public Mouse getMouse() {
        return mouse;
    }
    public void setMouse(Mouse mouse) {
        this.mouse = mouse;
    }
    public void play(){
        System.out.println(engine.getName()+keyboard.getName()+mouse.getName());
    };
}
//引擎类
class Engine implements Serializable{
    private String name;
    public Engine(String name){this.name=name;}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//键盘类
class Keyboard implements Serializable{
    private String name;
    public Keyboard(String name){this.name=name;}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//鼠标类
class Mouse implements Serializable{
    private String name;
    public Mouse(String name){this.name=name;}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
--------------------------------------------------------------------------------
public class ComputerClone {
    public Computer clone(Computer c){
        Computer c2 =null;
        try {
            ByteArrayOutputStream bas =new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bas);
            oos.writeObject(c);
            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bas.toByteArray()));
            c2 =(Computer) ois.readObject();
            bas.flush();oos.flush();
            bas.close();oos.close();
            ois.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return c2;
    }
}
--------------------------------------------------------------------------------
public class Client {
    public static void main(String[] args) {
        ComputerClone computerClone = new ComputerClone();
        Computer c = new Computer();
        c.setEngine(new Engine("华为CPU"));
        c.setKeyboard(new Keyboard("联想键盘"));
        c.setMouse(new Mouse("苹果鼠标"));
        Computer c2 = computerClone.clone(c);
        System.out.println(c);
        System.out.println(c2);
        System.out.println(c2.getEngine().getName()+""+c2.getKeyboard().getName()+""+c2.getMouse().getName()+"");
    }
}
--------------------------------------------------------------------------------
结果:
com.primeton.GOF23.prototype.Computer@6727734f
com.primeton.GOF23.prototype.Computer@7176c74b
华为CPU联想键盘苹果鼠标
--------------------------------------------------------------------------------
总结:通过结果可以看到克隆出来的对象是一个新对象,但其中属性与原型对象一致,整个新对象产生的过程很简单,效率高(直接克隆,避免了重新执行构造过程步骤) 

你可能感兴趣的:(GOF23(java设计模式)--创建型模式)