常用设计模式
一、OOP编程七大原则
PBP/OBP/OOP的特征
PBP(基于过程):函数、域与生命周期的概念、函数重载、函数模板、异常处理、范型算法。
OBP(基于对象):类(接口)、类的生命周期、类模板。
OOP(面向对象):继承、多态。
三个概念步步深入,后者包括前者。其目的是实现软件开发的可重用性,解决软件危机(软件工程思想未引入之前)。
OOP不可避免设计原则的发展与设计模式的产生,这是OOP独具的特征决定的(正如前面所说,特征的产生是由其产生目的决定的)。
OOP的方法论(高内聚、低耦合、易复用)
OOP的方法论--如何实现基于OOP特征的抽象?
OOP设计原则:
OCP(Open-Closed Principle),开放封闭原则:软件实体应该扩展开放、修改封闭。
实现:合理划分构件,一种可变性不应当散落在代码的很多角落里,而应当被封装到一个对象里;一种可变性不应当与另一个可变性混合在一起。
DIP(Dependency Inversion Principle),依赖倒置原则:摆脱面向过程编程思想中高层模块依赖于低层实现,抽象依赖于具体细节。OOP中要做到的是,高层模块不依赖于低层模块实现,二者都依赖于抽象;抽象不依赖于具体实现细节,细节依赖于抽象。
实现:应该通过抽象耦合的方式,使具体类最大可能的仅与其抽象类(接口)发生耦合;程序在需要引用一个对象时,应当尽可能的使用抽象类型作为变量的静态类型,这就是针对接口编程的含义。
LSP(Liskov Substitution Principle),Liskov替换原则:继承思想的基础。“只有当衍生类可以替换掉基类,软件单位的功能不会受到影响时,基类才真正被复用,而衍生类也才能够在基类的基础上增加新的行为。”
ISP(Interface Insolation Principle),接口隔离原则:接口功能单一,避免接口污染。
实现:一个类对另外一个类的依赖性应当是建立在最小的接口上的。使用多个专门的接口比使用单一的总接口要好。
SRP(Single Resposibility Principle),单一职责原则:就一个类而言,应该仅有一个引起它变化的原因。 如果一个类的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会抑止这个类完成其他职责的能力。
CARP(Composite/Aggregate Reuse Principle),合成/聚合复用原则:设计模式告诉我们对象委托优于类继承,从UML的角度讲,就是关联关系优于继承关系。尽量使用合成/聚合、尽量不使用继承。
实现:在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分,以整合其功能。
LoD(Law Of Demeter or Principle of Least Knowledge),迪米特原则或最少知识原则:就是说一个对象应当对其他对象尽可能少的了解。即只直接与朋友通信,或者通过朋友与陌生人通信。
朋友的定义(或关系):
(1)当前对象本身。
(2)以参量的形式传入到当前对象方法中的对象。
(3)当前对象的实例变量直接引用的对象。
(4)当前对象的实例变量如果是一个聚集,那么聚集中的元素也都是朋友。
(5)当前对象所创建的对象。
实现:
(1)在类的划分上,应当创建有弱耦合的类。类之间的耦合越弱,就越有利于复用。
(2)在类的结构设计上,每一个类都应当尽量降低成员的访问权限。一个类不应当public自己的属性,而应当提供取值和赋值的方法让外界间接访问自己的属性。
(3)在类的设计上,只要有可能,一个类应当设计成不变类。
(4)在对其它对象的引用上,一个类对其它对象的引用应该降到最低。
(5)尽量限制局部变量的有效范围.
二、单例模式
保证一个类只有一个对象
饿汉式
public class Hungry {
//可能会浪费空间
private byte[] data1 = new byte[1024*1024];
private byte[] data2 = new byte[1024*1024];
private byte[] data3 = new byte[1024*1024];
private byte[] data4 = new byte[1024*1024];
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
DCL懒汉式
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Lazy {
private static boolean qinjiang = false;
private Lazy(){
synchronized (Lazy.class){
if (qinjiang == false){
qinjiang = true;
} else {
throw new RuntimeException("不要试图使用反射破坏异常\n");
}
}
System.out.println(Thread.currentThread().getName()+"ok");
}
private volatile static Lazy lazy;
//双重检测锁模式的懒汉式单例 DCL懒汉式
public static Lazy getInstance(){
//加锁
if (lazy==null){
synchronized (Lazy.class){
if (lazy==null)
lazy = new Lazy(); //不是原子性操作
/*
1.分配内存空间
2.执行构造方法,初始化对象
3.把这个对象指向这个空间
*/
}
}
return lazy; //此时lazy还没有完成构造,所以必须volatile
}
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//多线程并发
for (int i = 0; i < 10; i++) {
new Thread(()->{
Lazy.getInstance();
}).start();
}
//反射破坏单例模式,解决:加变量qinjiang
Lazy instacne1 = Lazy.getInstance();
Constructor<Lazy> declaredConstructor = Lazy.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true); //无视私有构造器
Lazy instacne2 = declaredConstructor.newInstance();
System.out.println(instacne1); //singleton.Lazy@3d075dc0
System.out.println(instacne2); //singleton.Lazy@214c265e
}
}
静态内部类
public class Holder {
private Holder(){
}
public static Holder getInstance(){
return InnerClass.HOLDER;
}
public static class InnerClass{
private static final Holder HOLDER = new Holder();
}
}
单例不安全,都有反射
枚举
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
//enum本身是一个class类
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
class Test{
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
EnumSingle instance1 = EnumSingle.INSTANCE;
Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
EnumSingle instance2 = declaredConstructor.newInstance(String.class,int.class);
//NoSuchMethodException: singleton.EnumSingle.<init>()
System.out.println(instance1);
System.out.println(instance2);
}
}
三、工厂模式
实现了创建者和调用者的分离
核心本质:实例化对象不使用new,用工厂方法代替。将选择实现类,创建对象统一管理和控制,从而将调用者跟我们的实现类解耦。
简单/静态工厂模式
不满足开闭原则,再加新的产品时需要改代码
Car接口
public interface Car {
void name();
}
两个实现类
public class Tesla implements Car {
@Override
public void name() {
System.out.println("Tesla!");
}
}
public class Wuling implements Car {
@Override
public void name() {
System.out.println("五菱宏光!");
}
}
车工厂
public class CarFactory {
public static Car getCar(String car){
if (car.equals("五菱")) {
return new Wuling();
}else if (car.equals("tesla")){
return new Tesla();
}else {
return null;
}
}
}
测试类
public class Consumer {
public static void main(String[] args) {
//1.传统方法需要知道 接口和所有的实现类
//Car car1 = new Wuling();
//Car car2 = new Tesla();
//car1.name();
//car2.name();
//2.使用工厂
Car car1 = CarFactory.getCar("五菱");
Car car2 = CarFactory.getCar("tesla");
car1.name();
car2.name();
}
}
工厂方法模式
解决了开闭,但是每多一个产品都需要多写一个工厂
车工厂接口
public interface CarFactory {
Car getCar();
}
工厂实现类
public class TeslaFactory implements CarFactory {
@Override
public Car getCar() {
return new Tesla();
}
}
public class WulingFactory implements CarFactory{
@Override
public Car getCar() {
return new Wuling();
}
}
测试类
public class Consumer {
public static void main(String[] args) {
Car car1 = new WulingFactory().getCar();
Car car2 = new TeslaFactory().getCar();
}
}
抽象工厂模式
围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂
优点:
- 具体产品在应用层的代码隔离,无需关心创建的细节
- 将一个系列的产品统-到-起创建
缺点:
- 规定了所有可能被创建的产品集合,产品簇中扩展新的产品困难
- 增加了系统的抽象性和理解难度
产品接口
public interface IPhoneProduct {
void start();
void shutdown();
void callup();
void sendSMS();
}
public interface IRouterProduct {
void start();
void shutdown();
void openwifi();
void setting();
}
产品实现类
public class MIPhone implements IPhoneProduct {
@Override
public void start() {
System.out.println("开启小米手机");
}
@Override
public void shutdown() {
System.out.println("关闭小米手机");
}
@Override
public void callup() {
System.out.println("小米打电话");
}
@Override
public void sendSMS() {
System.out.println("小米发短信");
}
}
public class HuaweiPhone implements IPhoneProduct {
@Override
public void start() {
System.out.println("开启华为手机");
}
@Override
public void shutdown() {
System.out.println("关闭华为手机");
}
@Override
public void callup() {
System.out.println("华为打电话");
}
@Override
public void sendSMS() {
System.out.println("华为发短信");
}
}
public class MIRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("启动小米路由器");
}
@Override
public void shutdown() {
System.out.println("关闭小米路由器");
}
@Override
public void openwifi() {
System.out.println("小米路由器打开wifi");
}
@Override
public void setting() {
System.out.println("小米路由器设置");
}
}
public class HuaweiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("启动华为路由器");
}
@Override
public void shutdown() {
System.out.println("关闭华为路由器");
}
@Override
public void openwifi() {
System.out.println("华为路由器打开wifi");
}
@Override
public void setting() {
System.out.println("华为路由器设置");
}
}
抽象工厂接口
public interface IProductFactory {
//生产手机
IPhoneProduct iPhoneProduct();
//生产路由器
IRouterProduct iRouterProduct();
}
不同等级的产品工厂
public class MIFactory implements IProductFactory {
@Override
public IPhoneProduct iPhoneProduct() {
return new MIPhone();
}
@Override
public IRouterProduct iRouterProduct() {
return new MIRouter();
}
}
public class HuaweiFctory implements IProductFactory {
@Override
public IPhoneProduct iPhoneProduct() {
return new HuaweiPhone();
}
@Override
public IRouterProduct iRouterProduct() {
return new HuaweiRouter();
}
}
客户端
public class Client {
public static void main(String[] args) {
System.out.println("=====小米系列产品=====");
//小米工厂
MIFactory miFactory = new MIFactory();
IPhoneProduct iPhoneProduct = miFactory.iPhoneProduct();
iPhoneProduct.start();
IRouterProduct iRouterProduct = miFactory.iRouterProduct();
iRouterProduct.openwifi();
System.out.println("=====华为系列产品=====");
//华为工厂
HuaweiFctory huaweiFctory = new HuaweiFctory();
IPhoneProduct iPhoneProduct1 = huaweiFctory.iPhoneProduct();
iPhoneProduct1.callup();
IRouterProduct iRouterProduct1 = huaweiFctory.iRouterProduct();
iRouterProduct1.setting();
}
}
四、创建者模式
建造者模式也属于创建型模式,它提供了一种创建对象的最佳方式。
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。
用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建复杂对象(把内部的建造过程和细节隐藏起来
一般用法,有指挥者
产品
//产品:房子
public class Product {
private String buildA;
private String buildB;
private String buildC;
private String buildD;
public String getBuildA() {
return buildA;
}
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public String getBuildB() {
return buildB;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public String getBuildC() {
return buildC;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
public String getBuildD() {
return buildD;
}
public void setBuildD(String buildD) {
this.buildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' +
'}';
}
}
抽象的建造者
public abstract class Builder {
abstract void buildA(); //盖楼的四个步骤
abstract void buildB();
abstract void buildC();
abstract void buildD();
abstract Product getProduct(); //完工,得到产品
}
具体的建造者
public class Worker extends Builder {
private Product product;
public Worker(){
product = new Product();
}
@Override
void buildA() {
product.setBuildA("A");
System.out.println("A");
}
@Override
void buildB() {
product.setBuildB("B");
System.out.println("B");
}
@Override
void buildC() {
product.setBuildC("C");
System.out.println("C");
}
@Override
void buildD() {
product.setBuildD("D");
System.out.println("D");
}
@Override
Product getProduct() {
return product;
}
}
指挥类
//指挥:核心,决定了工作顺序(方式)
public class Director {
//指挥工人建房子
public Product build(Builder builder){
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD();
return builder.getProduct();
}
}
测试类
public class Test {
public static void main(String[] args) {
//新建一个指挥
Director director = new Director();
//指挥控制工人完成产品
//这里的例子是所有工作都由一类工人完成了
Product product = director.build(new Worker());
System.out.println(product.toString());
}
}
客户当指挥
产品
//产品:套餐,默认 ABCD 各一个
public class Product {
private String buildA = "汉堡";
private String buildB = "可乐";
private String buildC = "薯条";
private String buildD = "甜点";
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
public void setBuildD(String buildD) {
this.buildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' +
'}';
}
}
抽象建造者
public abstract class Builder {
abstract Builder buildA(String msg); //汉堡
abstract Builder buildB(String msg); //可乐
abstract Builder buildC(String msg); //薯条
abstract Builder buildD(String msg); //甜点
abstract Product getProduct();
}
具体建造者
public class Worker extends Builder {
private Product product;
public Worker(){
product = new Product();
}
@Override
Builder buildA(String msg) {
product.setBuildA(msg);
return this;
}
@Override
Builder buildB(String msg) {
product.setBuildB(msg);
return this;
}
@Override
Builder buildC(String msg) {
product.setBuildC(msg);
return this;
}
@Override
Builder buildD(String msg) {
product.setBuildD(msg);
return this;
}
@Override
Product getProduct() {
return product;
}
}
客户
public class Client {
public static void main(String[] args) {
//服务员
Worker worker = new Worker();
Product product = worker.getProduct(); //默认产品
System.out.println(product.toString());
//链式编程
product = worker.buildA("全家桶").buildC("雪碧").getProduct();
System.out.println(product.toString());
}
}
// 输出
// Product{buildA='汉堡', buildB='可乐', buildC='薯条', buildD='甜点'}
// Product{buildA='全家桶', buildB='可乐', buildC='雪碧', buildD='甜点'}
五、原型模式
以某个对象为原型,克隆出一个新的一模一样的对象
浅克隆
Video类
/*
1.实现一个接口 Cloneable
2.重写一个方法 clone()
*/
public class Video implements Cloneable{ //无良up,克隆别人的视频
private String name;
private Date createTime;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Video() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Video(String name, Date createTime) {
this.name = name;
this.createTime = createTime;
}
@Override
public String toString() {
return "Video{" +
"name='" + name + '\'' +
", createTime=" + createTime +
'}';
}
}
测试类
public class Bilibili {
public static void main(String[] args) throws CloneNotSupportedException {
//原型对象
Date date = new Date();
Video v1 = new Video("狂神java",date);
System.out.println("v1=>"+v1.toString());
System.out.println("v1.hash=>"+v1.hashCode());
//v1 克隆 v2
Video v2 = (Video)v1.clone();
System.out.println("v2=>"+v2.toString());
System.out.println("v2.hash=>"+v2.hashCode());
//改变v1的date,v2也跟着变,说明只是浅克隆
date.setTime(2333);
System.out.println("v1=>"+v1.toString());
System.out.println("v2=>"+v2.toString());
}
}
深克隆
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
Video v = (Video) obj;
//将对象的属性也克隆
v.setCreateTime((Date) this.createTime.clone());
return obj;
}
六、适配器模式
//要被适配的类: 网线
public class ToAdapter {
public void request(){
System.out.println("连接网线上网");
}
}
//接口转换器的抽象实现
public interface NetToUsb {
//作用:处理请求,网线=>USB
public void handleRequest();
}
//1.继承实现
//真适配器,需要连接电脑的USB,需要连接网线
public class Adapter extends ToAdapter implements NetToUsb{
@Override
public void handleRequest() {
super.request(); //可以上网了
}
}
//2.组合实现,热拔插式
public class Adapter2 implements NetToUsb{
private ToAdapter toAdapter;
public Adapter2(ToAdapter toAdapter) {
this.toAdapter = toAdapter;
}
@Override
public void handleRequest() {
toAdapter.request();
}
}
//客户端类:想上网,插不上网线
public class Computer {
//电脑需要连接转接器才能上网
public void net(NetToUsb adapter){
//上网的具体实现,找一个转接头
adapter.handleRequest();
}
public static void main(String[] args) {
//电脑,适配器,网线
Computer computer = new Computer();
ToAdapter toAdapter = new ToAdapter();
Adapter adapter = new Adapter();
computer.net(adapter);
Computer computer2 = new Computer();
Adapter2 adapter2 = new Adapter2(toAdapter);
computer.net(adapter2);
}
}
七、桥接模式
//品牌
public interface Brand {
void info();
}
//联想品牌
class Lenovo implements Brand{ //接口
@Override
public void info() {
System.out.print("Lenovo");
}
}
//苹果品牌
class Apple implements Brand{
@Override
public void info() {
System.out.print("Apple");
}
}
//抽象的电脑类
public abstract class Computer {
//组合:品牌 ~ ,computer has a brand
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void info(){
brand.info(); //自带品牌
}
}
class Desktop extends Computer{ //继承
public Desktop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.println("台式机");
}
}
class Laptop extends Computer{
public Laptop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.println("笔记本");
}
}
//测试类
public class Test {
public static void main(String[] args) {
//苹果笔记本
Computer computer = new Laptop(new Apple());
computer.info();
//联想台式机
Computer computer2 = new Desktop(new Lenovo());
computer2.info();
}
}
// 输出
// Apple笔记本
// Lenovo台式机
八、代理模式
Spring里介绍过的,笔记:https://www.cnblogs.com/peng8098/p/java_17.html
九、观察者模式
// Subject 类
public class Subject {
private List<Observer> observers
= new ArrayList<Observer>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for (Observer observer : observers) {
observer.update();
}
}
}
// Observer 类
public abstract class Observer {
protected Subject subject; //it has a subject
public abstract void update();
}
// 实体观察者类
public class BinaryObserver extends Observer{
public BinaryObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Binary String: "
+ Integer.toBinaryString( subject.getState() ) );
}
}
public class OctalObserver extends Observer{
public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Octal String: "
+ Integer.toOctalString( subject.getState() ) );
}
}
public class HexaObserver extends Observer{
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println( "Hex String: "
+ Integer.toHexString( subject.getState() ).toUpperCase() );
}
}
// 使用 Subject 和实体观察者对象测试
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();
new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);
System.out.println("First state change: 15");
subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}
输出
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010
十、策略模式
//步骤 1 创建一个接口
public interface Strategy {
public int doOperation(int num1, int num2);
}
//步骤 2 创建实现接口的实体类
public class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class OperationSubtract implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
public class OperationMultiply implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
//步骤 3 创建 Context 类。
public class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}
}
//步骤 4 使用 Context 来查看当它改变策略 Strategy 时的行为变化。
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
// 步骤 5执行程序,输出结果:
// 10 + 5 = 15
// 10 - 5 = 5
// 10 * 5 = 50
十一、B/S C/S 架构
C/S架构是什么?
C/S架构,即Client/Server(客户端/服务器)架构,是一个典型的两层架构。通过将任务合理分配到客户端和服务器,降低了系统的通讯开销,需要安装客户端才可进行管理操作。
客户端包含一个或多个运行在用户计算机上的程序,有两个服务器,一个是数据库服务器,通过数据库连接客户端访问服务器端数据;另一种是套接字服务器,服务器通过套接字程序与客户端通信。
客户端和服务器端的程序不同,用户的程序主要在客户端,服务器端主要提供数据管理、数据共享、数据及系统维护和并发控制等,客户端程序主要完成用户的具体的业务。
开发比较容易,操作简便,但应用程序的升级和客户端程序的维护较为困难。
B/S架构是什么?
B/S架构,即Brower/Server(浏览器/服务器)架构。它由逻辑上相互分离的表示层、业务层和数据层构成。表示层向客户提供数据,业务层实施业务和数据规则,数据层定义数据访问标准;三层体系结构中的核心是组件对象模型。
B / S系统统一了客户端,无需特殊安装,拥有Web浏览器即可;它将系统功能实现的核心部分集中到服务器上,简化了系统的开发、维护和使用。可以在服务器上安装数据库,然后浏览器通过mysql等数据库来进行数据交互。
1、建立基础不同
C/S是建立在局域网的基础上的;而,B/S是建立在广域网的基础上的。
2、硬件环境不同
C/S 一般建立在专用的网络上,小范围里的网络环境,局域网之间再通过专门服务器提供连接和数据交换服务。
B/S 建立在广域网之上的,不必有专门的网络硬件环境,例与电话上网,租用设备,信息自己管理。有比C/S更强的适应范围, 一般只要有操作系统和浏览器就行。
3、对安全要求不同
C/S 一般面向相对固定的用户群,对信息安全的控制能力很强。一般高度机密的信息系统采用C/S 结构适宜,可以通过B/S发布部分可公开信息.
B/S 建立在广域网之上, 对安全的控制能力相对弱, 面向是不可知的用户群。
4、对程序架构不同
C/S 程序更加注重流程, 可以对权限多层次校验, 对系统运行速度可以较少考虑。
B/S对安全以及访问速度的多重考虑, 建立在需要更加优化的基础之上。 比C/S有更高的要求 B/S结构的程序架构是发展的趋势, 从MS的。Net系列的BizTalk 2000 Exchange 2000等, 全面支持网络的构件搭建的系统。 SUN 和IBM推的JavaBean 构件技术等,使 B/S更加成熟。 例如智赢IPOWER,采用AJAX和数据存储优化技术,相比一般B/S架构软件速度提高30%至99%。
5、软件重用不同
C/S 程序不可避免的考虑整体性, 构件的重用性不如在B/S要求下的构件的重用性好。
B/S对的多重结构,要求构件相对独立的功能, 能够相对较好的重用。
6、系统维护不同
C/S 程序由于整体性, 必须整体考察, 处理出现的问题以及系统升级。 升级难, 可能是再做一个全新的系统
B/S 构件组成,方面构件个别的更换,实现系统的无缝升级。 系统维护开销减到最小;用户从网上自己下载安装就可以实现升级。
7、处理问题不同
C/S 程序可以处理用户面固定, 并且在相同区域, 安全要求高需求, 与操作系统相关。 应该都是相同的系统
B/S 建立在广域网上, 面向不同的用户群, 分散地域, 这是C/S无法作到的;与操作系统平台关系最小。
8、用户接口不同
C/S 多是建立的Window平台上,表现方法有限,对程序员普遍要求较高
B/S 建立在浏览器上, 通过WEB服务或其他公共可识别描述语言可跨平台,使用更灵活。不仅可应用在Window平台上,还可应用于unix/Linux等平台。
9、信息流不同
C/S 程序一般是典型的中央集权的机械式处理, 交互性相对低
B/S 信息流向可变化, B-B B-C B-G等信息、流向的变化, 更象交易中心。