天天看点

java工厂,代理,单例设计模式及其部分改善

java基础要求掌握三种重点设计模式:工厂,代理,单例。本文将针对工厂设计模式中的简单工厂模式,代理模式和单例模式这几块儿,我今天必须给大家讲的明明白白!

一.工厂设计模式.

1.简单工厂模式

简单工厂模式专门定义一个类用来创建其他类的实例,被创建的实例通常都具有共同的父类。

概要:1.一个抽象产品类

           2.具体产品类

           3.一个工厂

优点:简单易于实现,把类的实例化交给工厂,易于解耦。

缺点:添加具体产品需要修改工厂违反OCP开放封闭原则

以下是简单工厂模式:

package com.matajie;

import java.util.Scanner;

/**
 * Author:年仅18岁的天才少年程序员
 * *******Java猛男丶Mata杰
 * *******我的程序才没有BUG!!!
 */
interface Computer{
    void printComputer();
}
class MacComputer implements Computer{

    @Override
    public void printComputer() {
        System.out.println("this is a MacComputer");
    }
}
class SurComputer implements Computer{

    @Override
    public void printComputer() {
        System.out.println("this is a SurComputer");
    }
}
class Factory{
    public static Computer getInstance(String type){
        Computer computer = null;
        if(type.equals("MacComputer")){
            computer = new MacComputer();
        }else if (type.equals("SurComputer")){
            computer = new SurComputer();
        }else {
            System.out.println("无此商品");
        }
        return computer;
    }
}

public class Client {
    public void buyComputer(Computer computer){
        computer.printComputer();
    }

    public static void main(String[] args) {
        Client client = new Client();
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你想要的电脑");
        String type = scanner.nextLine();
        Computer computer = Factory.getInstance(type);
        client.buyComputer(computer);
    }
}
           

这种模式的缺点太过明显了,每增加一个接口的子类就需要修改工厂类,在实际开发中根本用不到,那么我们应该怎么改进呢?

没错!用反射啊!因为Class类可以使用newInstance()实例化对象,而且Class.forName()能够接收类名称。

改进(反射):

package com.matajie;

import java.util.Scanner;

/**
 * Author:年仅18岁的天才少年程序员
 * *******Java猛男丶Mata杰
 * *******我的程序才没有BUG!!!
 */
interface Computer{
    void printComputer();
}
class MacComputer implements Computer{

    @Override
    public void printComputer() {
        System.out.println("this is a MacComputer");
    }
}
class SurComputer implements Computer{

    @Override
    public void printComputer() {
        System.out.println("this is a SurComputer");
    }
}
class Factory{
    public static Computer getInstance(String type) throws ClassNotFoundException {
        Computer computer = null;
        try {
         Class<?> cls = Class.forName(type);//取得任意子类反射对象
            computer = (Computer) cls.newInstance();//通过反射取得实例化对象
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    return computer;
    }
}

public class Client {
    public static void main(String[] args) throws ClassNotFoundException {
        Computer computer =Factory.getInstance("com.matajie.MacComputer");
             computer.printComputer();
    }
}
           

这样,我们就可以很方便的进行接口子类扩容

2.工厂方法模式.

定义一个用来创建对象的接口,让子类决定实例化哪一个类。

概要

1. 一个抽象产品类

2. 多个具体产品类

3. 一个抽象工厂

4. 多个具体工厂 - 每一个具体产品对应一个具体工厂

优点:降低了代码耦合度,对象的生成交给子类去完成

实现了开放封闭原则 - 每次添加子产品 不需要修改原有代码

缺点:增加了代码量,每个具体产品都需要一个具体工厂

当增加抽象产品 也就是添加一个其他产品族 需要修改工厂 违背OCP

package com.matajie;

import java.util.Scanner;

/**
 * Author:年仅18岁的天才少年程序员
 * *******Java猛男丶Mata杰
 * *******我的程序才没有BUG!!!
 */
interface Computer{
    void printComputer();
}
class MacComputer implements Computer{

    @Override
    public void printComputer() {
        System.out.println("this is a MacComputer");
    }
}
class SurComputer implements Computer{

    @Override
    public void printComputer() {
        System.out.println("this is a SurComputer");
    }
}
interface ComputerFactory{
    Computer creataComputer();
}
class MacFactory implements ComputerFactory{

    @Override
    public Computer creataComputer() {
        return new MacComputer();
    }
}
class SurFactory implements ComputerFactory{

    @Override
    public Computer creataComputer() {
        return new SurComputer();
    }
}
public class Client{
    public void buyComputer(Computer computer){
        computer.printComputer();
    }

    public static void main(String[] args) {
        Client client = new Client();
        ComputerFactory factory = new MacFactory();
        client.buyComputer(factory.creataComputer());
    }
}
           

3.抽象工厂模式

抽象工厂模式就是在工厂方法模式上进行了扩展,它把原先的工厂方法模式中只能有一个抽象产品不能添加产品族的缺点克服了

概要:1.多个抽象产品类

           2.具体产品类

           3.抽象工厂类声明一组返回抽象产品的方法

           4.具体工厂类生命一组具体产品

优点:代码解耦

实现多个产品族(相关联产品组成的家族),而工厂方法模式的单个产品,可以满足更多的生产需求

很好的满足OCP开放封闭原则

抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类 对于复杂对象的生产

相当灵活易扩展

缺点:扩展产品族相当麻烦 而且扩展产品族会违反OCP,因为要修改所有的工厂

由于抽象工厂模式是工厂方法模式的扩展 总体的来说很笨重。

package com.matajie;

import java.util.Scanner;

/**
 * Author:年仅18岁的天才少年程序员
 * *******Java猛男丶Mata杰
 * *******我的程序才没有BUG!!!
 */
interface Computer{
    void printComputer();
}
class MacComputer implements Computer{

    @Override
    public void printComputer() {
        System.out.println("this is a MacComputer");
    }
}
class SurComputer implements Computer{

    @Override
    public void printComputer() {
        System.out.println("this is a SurComputer");
    }
}
interface OperatingSystem{
    void printSystem();
}
class MacOsSystem implements OperatingSystem{

    @Override
    public void printSystem() {
        System.out.println("this is a MacOsSystem");
    }
}
class Windows8System implements OperatingSystem{

    @Override
    public void printSystem() {
        System.out.println("this is a Windows8System");
    }
}
interface ProductionFactory{
    Computer createComputer();
    OperatingSystem createSystem();
}
class AppleFactory implements ProductionFactory{

    @Override
    public Computer createComputer() {
        return new MacComputer();
    }

    @Override
    public OperatingSystem createSystem() {
        return new MacOsSystem();
    }
}
class MsFactory implements ProductionFactory{

    @Override
    public Computer createComputer() {
        return new SurComputer();
    }

    @Override
    public OperatingSystem createSystem() {
        return new Windows8System();
    }
}
public class Client{
    public void buyComputer(Computer computer){
        computer.printComputer();
    }
    public void use(OperatingSystem system){
        system.printSystem();
    }

    public static void main(String[] args) {
        Client client = new Client();
        ProductionFactory factory = new AppleFactory();
        Computer computer = factory.createComputer();
        OperatingSystem system =factory.createSystem();
        client.buyComputer(computer);
        client.use(system);
    }
}
           

工厂设计模式总结:

简单工厂模式最大的优点就是工厂内有具体的逻辑去判断生成什么产品,将类的实例化交给了工厂,这样当

我们需要什么产品只需要修改工厂的调用而不需要去修改客户端,对于客户端来说降低了与具体产品的依赖

工厂方法模式是简单工厂的扩展,工厂方法模式把原先简单工厂中的实现那个类的逻辑判断交给了客户端,

如果像添加功能只需要修改客户和添加具体的功能,不用去修改之前的类。

抽象工厂模式进一步扩展了工厂方法模式,它把原先的工厂方法模式中只能有一个抽象产品不能添加产品族

的缺点克服了,抽象工厂模式不仅仅遵循了OCP原则,而且可以添加更多产品(抽象产品),具体工厂也不仅仅

可以生成单一产品,而是生成一组产品,抽象工厂也是声明一组产品,对应扩展更加灵活,但是要是扩展族

系就会很笨重。

二:代理模式与改进

两个子类共同实现一个接口,其中一个子类负责真实业务实现,另外一个子类完成辅助真实业务主体的操作

package com.matajie;

import java.lang.reflect.Proxy;

/**
 * Author:年仅18岁的天才少年程序员
 * *******java猛男丶Mata杰
 * *******我的程序才没有BUG!!!
 */
interface ISubject{
    void buyComputer();
}
class RealSubject implements ISubject{

    @Override
    public void buyComputer() {
        System.out.println("买电脑");
    }
}
class ProxySubject implements ISubject{
    private ISubject subject;
    public ProxySubject(ISubject subject){
        this.subject =subject;
    }
    public void produceComputer(){
        System.out.println("生产电脑");
    }
    public void afterSafe(){
        System.out.println("售后");
    }
    @Override
    public void buyComputer() {
          this.produceComputer();
          this.subject.buyComputer();//调用真实业务
          this.afterSafe();
    }
}
class Factory{
    public static ISubject getInstance(){
        return new ProxySubject(new RealSubject());
    }
}
public class Test {
    public static void main(String[] args) {
        ISubject subject =Factory.getInstance();
        subject.buyComputer();
    }
}
           

这种代理模式只能够代理一个接口的子类对象,无法代理更多的接口子类对象。那么怎么解决呢?

动态代理模式:

一个代理类可以代理所有需要被代理的接口的子类对象

interface ISubject{
    public void printComputer(String msg,int num);
}
class RealSubject implements ISubject{

    @Override
    public void printComputer(String msg, int num) {
        System.out.println("我想买个"+num+"元的"+msg);
    }
}
class ProxySubject implements InvocationHandler{
      private Object target;//绑定任意的接口对象,使用Object描述
      public Object bind(Object target){//实现真实对象的绑定处理,同时返回代理对象
          this.target =target;//保存真实对象
          return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
      }//返回一个代理对象(这个对象是根据接口定义动态创建生成的代理对象)
      public void preHandle(){
          System.out.println("[ProxySubject]方法处理前");
      }
      public void afterHandle(){
          System.out.println("[afterSubject]方法处理后");
      }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        this.preHandle();
        Object ret = method.invoke(this.target,args);//反射调用方法
        this.afterHandle();
        return ret;
    }
}
public class Test{
    public static void main(String[] args) {
        ISubject subject = (ISubject) new ProxySubject().bind(new RealSubject());
        subject.printComputer("苹果电脑",8000);
    }
}

           

三.单例模式的8种写法(这里不对不安全单例做说明)

单例模式:一个类只允许产生一个实例化对象,构造方法私有化。

1.饿汉式(普通)单例:(线程安全,可用)

public class Singleton {
    private final static Singleton INSTANCE = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return INSTANCE;
    }
}
           

2.饿汉式(静态代码块)(线程安全,可用)

public class Singleton{
    private static Singleton instance;
    static {
        instance = new Singleton();
    }
    private Singleton(){}
    public static Singleton getInstance(){
        return instance;
    }
}
           

3.双重检查(线程安全,建议用)

public class Singleton{
    private static volatile Singleton singleton;
    private Singleton(){}
    public static Singleton getSingleton(){
        if(singleton == null){
            synchronized (Singleton.class){
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}
           

4.静态内部类(线程安全,建议用)

public class Singleton{
    private Singleton(){}
    public static class SingletonInstance{
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }
}
           

5.枚举(极推荐用)

public enum Singleton{
    INSTANCE;
    public void method(){
        
    }
}
           

有哪里可以改进的地方希望大家多多指教。